Changes between Version 15 and Version 16 of CALプログラミング(1)


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

--

Legend:

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

    v15 v16  
    33 
    44= 簡単なプログラム = 
    5  * 一番簡単なテストプログラムが"/usr/local/amdcal/samples/app/hellocal"(CALをインストールしたディレクトリ)にある。これをコピーして、不必要なものを取り除いたバージョンのプログラムが[attachment:CALTEST.tar.gz]にあるので、これを自分のホームディレクトリに展開する。 
     5一番簡単なテストプログラムが"/usr/local/amdcal/samples/app/hellocal"(CALをインストールしたディレクトリ)にある。これをコピーして、不必要なものを取り除いたバージョンのプログラムが[attachment:CALTEST.tar.gz]にあるので、これを自分のホームディレクトリに展開する。 
    66 
    7  * makeすることで、"hellocal"というプログラムが作られる。 
     7makeすることで、"hellocal"というプログラムが作られる。 
    88 
    9  * まずはこのプログラムを実行してみること。何かキーを押したら終了する。  
    10    * 実行例 
     9まずはこのプログラムを実行してみること。何かキーを押したら終了する。  
     10 
     11実行例 
    1112{{{ 
    1213gpu1[~/CALTEST] ./hellocal                                                                                     
     
    2425 
    2526= hellocalの解説 = 
    26  * このテストプログラムは、'''入力されたデータに0.5を掛けるという演算'''をGPUでおこなって、結果を得るというプログラムである。 
     27このテストプログラムは、'''入力されたデータに0.5を掛けるという演算'''をGPUでおこなって、結果を得るというプログラムである。 
    2728 
    28  * 入力データは"hellocal.cpp"の118行の2重ループで値が設定されている変数fdata[]である。102行で、inputResが定義されている。この定義から、inputResが256x256の浮動小数点変数であることがわかる。C言語の配列で書くとfloat array[256][256]になる。116行と117行において、inputResとfdataがマッピングされていることを確認すること。これにより、fdata[]に代入したデータは、GPU上のメモリ(inputRes)に転送されることになる。同様に、出力データが103行で定義されていて、結果を得るために、190行でfdata[](このポインタ変数は2重の役割を果たしている)にマッピングされている事を確認すること。191行からのループにより、GPU上のメモリ(outputRes)から、結果を回収して出力していることを確認すること。  
     29入力データは"hellocal.cpp"の118行の2重ループで値が設定されている変数fdata[]である。102行で、inputResが定義されている。この定義から、inputResが256x256の浮動小数点変数であることがわかる。C言語の配列で書くとfloat array[256][256]になる。116行と117行において、inputResとfdataがマッピングされていることを確認すること。これにより、fdata[]に代入したデータは、GPU上のメモリ(inputRes)に転送されることになる。 
    2930 
    30  * 入力データが256x256であることから、計算に利用されるdomainが決定される(176行にて定義)。domainとは、単純には計算に利用されるGPU上のプロセッサの(論理的な)数だと思えばよい。つまりこの場合、論理的には256x256=65536個のプロセッサにより、65536個の入力データへの演算が並列に実行されると考える。この時に並列に実行されるプログラムをCALでの「kernelプログラム」と呼ぶ 
     31同様に、出力データが103行で定義されていて、結果を得るために、190行でfdata[](このポインタ変数は2重の役割を果たしている)にマッピングされている事を確認すること。191行からのループにより、GPU上のメモリ(outputRes)から、結果を回収して出力していることを確認すること 
    3132 
    32  * このプログラムの場合、kernelプログラムは24-33行で定義されている。コピーすると以下の通り(先頭は行番号):  
     33入力データが256x256であることから、計算に利用されるdomainが決定される(176行にて定義)。domainとは、単純には計算に利用されるGPU上のプロセッサの(論理的な)数だと思えばよい。つまりこの場合、論理的には256x256=65536個のプロセッサにより、65536個の入力データへの演算が並列に実行されると考える。この時に並列に実行されるプログラムをCALでの「kernelプログラム」と呼ぶ。  
     34 
     35このプログラムの場合、kernelプログラムは24-33行で定義されている。コピーすると以下の通り(先頭は行番号):  
    3336{{{ 
    3437 1 il_ps_2_0 
     
    4245}}} 
    4346 
    44  * '''このkernelプログラムが、個々の論理的なプロセッサで並列に(独立に)実行されるというのが、CALのプログラミングモデルである'''(これ重要)。kernelプログラムが実行されるときには、個々のプロセッサに、一意の番号が割り振られる。この番号は、UNIXなどでの"process id"に相当するものである。CALプログラミングにおいては、この番号はdomainの定義に応じて2次元で表される。つまり、このプログラムの場合には、(0,0)から(255,255)までの65536個の番号が割り振られることになる。 
     47'''このkernelプログラムが、個々の論理的なプロセッサで並列に(独立に)実行されるというのが、CALのプログラミングモデルである'''(これ重要)。kernelプログラムが実行されるときには、個々のプロセッサに、一意の番号が割り振られる。この番号は、UNIXなどでの"process id"に相当するものである。CALプログラミングにおいては、この番号はdomainの定義に応じて2次元で表される。つまり、このプログラムの場合には、(0,0)から(255,255)までの65536個の番号が割り振られることになる。 
    4548 
    46  * このkernelプログラムにおいて、「入力されたデータに0.5を掛けるという演算」は7行で定義されている。CALのILアセンブラは、"命令 出力変数 入力1 入力2"というフォーマットなので、この行の意味は「r0にcb0[0]を掛けてo0に格納する」ことになる。変数cb0[0]は4行で定義されており、これは大きさが1であるcb0という定数配列を定義するという宣言文である。また、変数o0は3行で定義されており、これはこの変数を出力に利用するという宣言文である。 
     49このkernelプログラムにおいて、「入力されたデータに0.5を掛けるという演算」は7行で定義されている。CALのILアセンブラは、"命令 出力変数 入力1 入力2"というフォーマットなので、この行の意味は「r0にcb0[0]を掛けてo0に格納する」ことになる。変数cb0[0]は4行で定義されており、これは大きさが1であるcb0という定数配列を定義するという宣言文である。また、変数o0は3行で定義されており、これはこの変数を出力に利用するという宣言文である。 
    4750 
    48  * 残ったのは変数r0であり、これが入力データに対応する。6行は、他の変数とは違い宣言文ではなく、「変数r0に入力データを読み込む」という意味を持つ。5行目のような宣言文とセットで利用すると覚えること。 
     51残ったのは変数r0であり、これが入力データに対応する。6行は、他の変数とは違い宣言文ではなく、「変数r0に入力データを読み込む」という意味を持つ。5行目のような宣言文とセットで利用すると覚えること。 
    4952 
    50  * さて、問題は、256x256で設定された入力データfdata[]のどのデータが読み込まれるのかということである。実はこれは、6行のふたつめの変数である"v0.xyxx"にて指定されている。変数v0とはなんだろうか?これは2行目で宣言されている。この行は、上で説明した「一意の番号」を"v0.xy"に読み込むということを表している。この2行目の宣言により、1番目のプロセッサではv0.x=0, v0.y=0となり、2番目のプロセッサではv0.x=1, v0.y=0、3番目のプロセッサではv0.x=3, v0.y=0...と続き、65536番目のプロセッサではv0.x=255, v0.y=255という「一意の番号」が個々のプロセッサに割りあてられることになる。 
     53さて、問題は、256x256で設定された入力データfdata[]のどのデータが読み込まれるのかということである。実はこれは、6行のふたつめの変数である"v0.xyxx"にて指定されている。変数v0とはなんだろうか?これは2行目で宣言されている。この行は、上で説明した「一意の番号」を"v0.xy"に読み込むということを表している。この2行目の宣言により、1番目のプロセッサではv0.x=0, v0.y=0となり、2番目のプロセッサではv0.x=1, v0.y=0、3番目のプロセッサではv0.x=3, v0.y=0...と続き、65536番目のプロセッサではv0.x=255, v0.y=255という「一意の番号」が個々のプロセッサに割りあてられることになる。 
    5154 
    52  * よって、6行目の意味を具体的に書くと「変数r0に入力リソース0(2次元)のv0.xy番地を読み込む」という意味となる。C言語で書き直すと、以下のような意味となる: 
     55よって、6行目の意味を具体的に書くと「変数r0に入力リソース0(2次元)のv0.xy番地を読み込む」という意味となる。C言語で書き直すと、以下のような意味となる: 
    5356{{{ 
    5457 r0 = i0[v0.x][v0.y] 
    5558}}} 
    5659 
    57  * なお、入力データがなぜ"i0"という変数になるかというと、6行で"resource(0)"となっているから。この変数"i0"はhellocal.cppの165行にあらわれる。これにより、inputResがkernelプログラムの"i0"という変数に対応することがわかる。 
     60なお、入力データがなぜ"i0"という変数になるかというと、6行で"resource(0)"となっているから。この変数"i0"はhellocal.cppの165行にあらわれる。これにより、inputResがkernelプログラムの"i0"という変数に対応することがわかる。 
    5861 
    59  * 変数o0については、なぜかデータが保存される番地が自動的に決定される。実は、その番地はv0.xyと同じである。よって、6行と7行を合わせて、具体的に書くと以下のようなC言語のプログラムとなる(変数は全てfloat変数。ただしcb0については次の説明に注意すること): 
     62変数o0については、なぜかデータが保存される番地が自動的に決定される。実は、その番地はv0.xyと同じである。よって、6行と7行を合わせて、具体的に書くと以下のようなC言語のプログラムとなる(変数は全てfloat変数。ただしcb0については次の説明に注意すること): 
    6063{{{ 
    6164 o0[v0.x][v0.y] = i0[v0.x][v0.y]*cb0[0] 
    6265}}} 
    6366 
    64  * すなわち、変数cb0[0]に0.5がはいっていれば、最初に書いた「入力されたデータに0.5を掛けるという演算」が実現できることになる。それをふまえた上で、hellocal.cppに戻ると、128-138行と166行において変数cb0[0]が定義、マッピングされていることがわかる。細かい点として、136,137行でcb0[0]に転送される定数データを指定しているが、実はkernelプログラムの4行における定数配列宣言は、4要素のベクトル定数の宣言になる。つまり、4行の宣言は、C言語では"cb0[0][4]"に相当する(CAL上では4要素へのアクセスを"xyzw"のmaskにより指定することに注意)。よって、hellocal.cppにおけるconstPtr[]への値の代入は、cb0[0].xyzwの代入に対応する。具体的には以下のようになる: 
     67すなわち、変数cb0[0]に0.5がはいっていれば、最初に書いた「入力されたデータに0.5を掛けるという演算」が実現できることになる。それをふまえた上で、hellocal.cppに戻ると、128-138行と166行において変数cb0[0]が定義、マッピングされていることがわかる。細かい点として、136,137行でcb0[0]に転送される定数データを指定しているが、実はkernelプログラムの4行における定数配列宣言は、4要素のベクトル定数の宣言になる。つまり、4行の宣言は、C言語では"cb0[0][4]"に相当する(CAL上では4要素へのアクセスを"xyzw"のmaskにより指定することに注意)。よって、hellocal.cppにおけるconstPtr[]への値の代入は、cb0[0].xyzwの代入に対応する。具体的には以下のようになる: 
    6568{{{ 
    6669 constPtr[0] -> cb0[0].x 
     
    7073}}} 
    7174 
    72  * 結果として、このプログラムを実行した場合、kernelプログラムのcb0[0]は以下のようになる。 
     75結果として、このプログラムを実行した場合、kernelプログラムのcb0[0]は以下のようになる。 
    7376{{{ 
    7477 cb0[0].x = 0.5, cb0[0].y = 0.0, cb0[0].z = 0.0, cb0[0].w = 0.0 
     
    7780= CALプログラミング(1)課題 = 
    7881 * hellocal.cppを変更して「入力されたデータに0.1を掛けるという演算」を実行するようにせよ。  
    79    * 実行例: 
     82   実行例: 
    8083{{{ 
    8184gpu1[~/CALTEST] ./hellocal                                                                                      [20:26] 
     
    9396 
    9497 * hellocal.cppを変更して「入力されたデータに0.1を掛けて、さらに10.0を足すという演算」を実行するようにせよ。 
    95    * 実行例: 
     98   実行例: 
    9699{{{ 
    97100gpu1[~/CALTEST] ./hellocal