Changes between Version 18 and Version 19 of CALプログラミング(4)


Ignore:
Timestamp:
Mar 22, 2009 1:15:32 PM (16 years ago)
Author:
nakasato
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • CALプログラミング(4)

    v18 v19  
    33 
    44= N体計算 = 
    5  * ここまでの説明を理解することで、最もシンプルなN体計算プログラムを作成できると思う。 
     5ここまでの説明を理解することで、最もシンプルなN体計算プログラムを作成できると思う。 
    66 
    7  * 具体的にはGRAPEなどと同じように、ホストから粒子の位置と質量をGPUに送り、GPU上で全粒子間で互いに及ぼし合う力を足しあわせて、結果として加速度を得るようなプログラムである。粒子間に働く力がニュートン重力の場合は、[http://galaxy.u-aizu.ac.jp/trac/note/attachment/wiki/CALによるGPUプログラミング/CAL200808.pdf  CAL200808.pdf] (60ページ以降)で説明しているIL kernelプログラムとなる。ループの部分のみを再掲すると、以下のようなものである。 
     7具体的にはGRAPEなどと同じように、ホストから粒子の位置と質量をGPUに送り、GPU上で全粒子間で互いに及ぼし合う力を足しあわせて、結果として加速度を得るようなプログラムである。粒子間に働く力がニュートン重力の場合は、[http://galaxy.u-aizu.ac.jp/trac/note/attachment/wiki/CALによるGPUプログラミング/CAL200808.pdf  CAL200808.pdf] (60ページ以降)で説明しているIL kernelプログラムとなる。ループの部分のみを再掲すると、以下のようなものである。 
    88{{{ 
    99 1  whileloop 
     
    2727}}} 
    2828  
    29  * データ構造の定義の詳細についてはファイルを参照のこと。 
     292粒子間の重力の計算をおこなっている部分は5-12行である。データ構造の定義の詳細についてはファイルを参照のこと。 
    3030 
    31  * 2粒子間の重力の計算をおこなっている部分は5-12行である。 
    32  
    33  * このILプログラムは、基本構造は(3)と同じであるが、ポインタ変数(ここでは"!r2.xy")の処理が異なる。なぜかというと、粒子の座標が格納されているid = 0のリソースは2次元のメモリとして指定、確保されているからである。具体的には、ホスト側のプログラムで以下のようにメモリの確保をおこなった: 
     31このILプログラムは、基本構造は(3)と同じであるが、ポインタ変数(ここでは!r2.xy)の処理が異なる。なぜかというと、粒子の座標が格納されているid = 0のリソースは2次元のメモリとして指定、確保されているからである。具体的には、ホスト側のプログラムで以下のようにメモリの確保をおこなった: 
    3432{{{ 
    3533  calResAllocLocal2D(&inputRes, device, nx, ny,  CAL_FORMAT_FLOAT_4, 0); 
    3634}}} 
    3735 
    38  * こうする大きな理由は、"calResAllocLocal1D"により1次元のメモリとして確保した場合、その次元の最大値は8192までという制限があるためである。よって、上のILプログラムの場合には、1粒子のデータとして4要素のfloatと変数を使っているので、1次元メモリで単純にN体計算を実装すると8192粒子までの粒子しか扱うことができない。これでは実質的に利用価値がなく、実際にベンチマークテストをしてみると、この粒子数ではRV770の性能を引き出すことができない。 
     36こうする理由は、"calResAllocLocal1D"により1次元のメモリとして確保した場合、その次元の最大値は8192までという制限があるためである。よって、上のILプログラムの場合には、1粒子のデータとして4要素のfloatと変数を使っているので、1次元メモリで単純にN体計算を実装すると8192粒子までの粒子しか扱うことができない。これでは実用的な価値がなく、実際にベンチマークテストをしてみると、この粒子数ではRV770の性能を引き出すことができない。 
    3937 
    4038= 2次元配列 = 
    41  * 2次元のメモリからデータを読み出すには、(3)では無視してきた読み込みポインタのy成分を適切にアップデートすればよい。上のILプログラムでは、13-18行の部分でその処理をおこなっている。 
     392次元のメモリからデータを読み出すには、(3)では無視してきた読み込みポインタのy成分を適切にアップデートすればよい。上のILプログラムでは、13-18行の部分でその処理をおこなっている。 
    4240 
    43  * 繰り返しになるが、読み込みポインタとデータの対応関係は: 
     41繰り返しになるが、読み込みポインタとデータの対応関係は: 
    4442{{{ 
    4543v0.xy = {0.0, 0.0} ---> res0[0][0] 
     
    4947v0.xy = {0.0, 1.0} ---> res0[1][0] 
    5048v0.xy = {1.0, 1.0} ---> res0[1][1] 
     49v0.xy = {2.0, 1.0} ---> res0[2][1] 
    5150 ... 
    5251}}} 
    5352 のようになっている。 
    5453 
    55  * それを踏まえて13-18行をC言語に翻訳してみると、処理内容が理解できると思う: 
     54それを踏まえて13-18行をC言語に翻訳してみると、処理内容が理解できると思う: 
    5655{{{ 
    5756  r2.x = r2.x + l1.x; 
     
    6362}}} 
    6463 
    65  * 変数の意味と定数の値はそれぞれ以下のとおり: 
     64変数の意味と定数の値はそれぞれ以下のとおり: 
    6665||!r2.xy   || 配列読み込みのポインタ  || 
    6766||!l1.x    || 浮動小数点定数 1.0  || 
     
    6968||!l0.z    || 整数定数 1 || 
    7069||!r77.y   || 整数定数 配列の最下位次元の大きさ 256 || 
    71  "!r77.y"の意味について補足すると、256になるのは、id = 0のメモリが"res0![256]![256]"として宣言されているからである。 
    7270 
    73  * よってILプログラムのこの部分は、2次元配列のポインタ演算をおこなっているのと同等である。細かく説明すると、!r2.x(1次元目の添え字に対応)が0から1ずつ増えていき、256に等しくなったたら、それを0にクリアし、!r2.y(2次元目の添え字に対応)をインクリメントしている。 
     71!r77.yの意味について補足すると、256になるのは、id = 0のメモリが"res0![256]![256]"として宣言されているからである。 
     72 
     73よってILプログラムのこの部分は、2次元配列のポインタ演算をおこなっているのと同等である。細かく説明すると、!r2.x(1次元目の添え字に対応)が0から1ずつ増えていき、256に等しくなったたら、それを0にクリアし、!r2.y(2次元目の添え字に対応)をインクリメントしている。 
    7474  
    75  * この13-18行を基にすることで、任意のサイズの2次元配列のランダムアクセスが可能であることがわかると思う。このILプログラムの場合、アクセスパターンが一定でありバースト的なため、GPUの内部構造に(特にキャッシュ機構)に適しており、非常に高速に動作する。一方、もしランダムアクセスを実装すると、メモリ読み込みのレイテンシーがパフォーマンスの問題となる可能性がある。 
     75この13-18行を基にすることで、任意のサイズの2次元配列のランダムアクセスが可能であることがわかると思う。このILプログラムの場合、アクセスパターンが一定でありバースト的なため、GPUの内部構造に(特にキャッシュ機構)に適しており、非常に高速に動作する。一方、もしランダムアクセスを実装すると、メモリ読み込みのレイテンシーがパフォーマンスの問題となる可能性がある。 
    7676 
    77  * "calResAllocLocal2D"または"calResAllocRemote2D"で確保した場合でも、それぞれの次元でのサイズの最大値は8192と思われる。よって、ひとつのメモリ領域に割り当て可能な最大メモリ量は、256M個のfloat変数(またはLocalの場合、ボードの搭載メモリ量の制限値まで)になる。(この項詳しく調べる必要あり) 
     77"calResAllocLocal2D"または"calResAllocRemote2D"で確保した場合でも、それぞれの次元でのサイズの最大値は8192と思われる。よって、ひとつのメモリ領域に割り当て可能な最大メモリ量は、256M個のfloat変数(またはLocalの場合、ボードの搭載メモリ量の制限値まで)になる。(この項詳しく調べる必要あり) 
    7878 
    79