Changes between Version 13 and Version 14 of CALプログラミング(3)


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

--

Legend:

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

    v13 v14  
    33 
    44= ループの例 = 
    5  * 何か役立つ計算をおこなうためには、ループ処理が必須となる。CALでループ処理を実装してみよう。 
     5何か役立つ計算をおこなうためには、ループ処理が必須となる。CALでループ処理を実装してみよう。 
    66 
    7  * [attachment:CALTEST3.tar.gz CALTEST3.tar.gz]にループを使った計算例のプログラムを置いたので、自分のディレクトリにコピーして実行すること。 
     7[attachment:CALTEST3.tar.gz CALTEST3.tar.gz]にループを使った計算例のプログラムを置いたので、自分のディレクトリにコピーして実行すること。 
    88{{{ 
    99gpu1[~/CALTEST3] ./hellocal 
     
    1414}}} 
    1515 
    16  * このプログラムは、1から10までの合計を計算するプログラムである。 
     16このプログラムは、1から10までの合計を計算するプログラムである。 
    1717 
    18  * なお、このプログラムから、kernelプログラムは別ファイルとして処理している。"hellocal.cpp"の34-51行にて、"prog.il"というファイルを読み込んでいる。kernelプログラムのみに変更を加える場合には、このファイルを変更するだけでよくて、再度makeする必要はない。 
     18なお、このプログラムから、kernelプログラムは別ファイルとして処理している。"hellocal.cpp"の34-51行にて、"prog.il"というファイルを読み込んでいる。kernelプログラムのみに変更を加える場合には、このファイルを変更するだけでよくて、再度makeする必要はない。 
    1919 
    20  * "hellocal.cpp"の本体部分は、これまでのプログラムとほとんど変わりがない。入出力用の配列を2次元から1次元としたことが大きな違いである。69-70行で、"calResAllocLocal1D()"によって1次元のメモリを確保している。この入力用のメモリには、78-84行にて1からnx(=256)の数字を代入している。 
     20"hellocal.cpp"の本体部分は、これまでのプログラムとほとんど変わりがない。入出力用の配列を2次元から1次元としたことが大きな違いである。69-70行で、"calResAllocLocal1D()"によって1次元のメモリを確保している。この入力用のメモリには、78-84行にて1からnx(=256)の数字を代入している。 
    2121 
    22  * 計算domainは(0, 0, 256, 1)としている(109行)ので、256個の論理プロセッサにて"prog.il"が実行される。 
     22計算domainは(0, 0, 256, 1)としている(109行)ので、256個の論理プロセッサにて"prog.il"が実行される。 
    2323 
    24  * kernelプログラムは、前と比べるとかなり変更がある。重要な変更点は: 
     24kernelプログラムは、前と比べるとかなり変更がある。重要な変更点は: 
    2525   1. "dcl_literal"による定数値の宣言と利用 
    2626   2. "whileloop"によるループ処理の記述 
    2727   3. データを読み込むポインタの更新 
    2828 
    29  以下、個々の点について詳しく説明する。 
     29以下、個々の点について詳しく説明する。 
    3030 
    3131= 定数について = 
    32  * wiki:"CALプログラミング(1)"のプログラムでは、浮動小数点整数をホストプログラムから転送していたが、CALでは定数値を直接プログラム中で利用することもできる。今回のプログラムでは"l0"と"l1"という定数値が5-6行で定義されている。 
     32wiki:"CALプログラミング(1)"のプログラムでは、浮動小数点整数をホストプログラムから転送していたが、CALでは定数値を直接プログラム中で利用することもできる。今回のプログラムでは"l0"と"l1"という定数値が5-6行で定義されている。 
    3333{{{ 
    3434dcl_literal 変数名, xの値, yの値, zの値, wの値 
     
    3636 というように宣言する。4要素を持つ変数であることに注意すること。整数を書けばそのままであり、"0xXX"とすれば16進数になるし、小数点が含まれる数は浮動小数点として扱われる。 
    3737 
    38  * 5-6行での宣言により、CAL上では以下のような定数として、"l0"と"l1"を利用できる。 
     385-6行での宣言により、CAL上では以下のような定数として、"l0"と"l1"を利用できる。 
    3939{{{ 
    4040l0.x = 0.0f, l0.y = 0.0f, l0.z = 1.0f, l0.w = 0.0f 
     
    4747 となる。"l1"も同様に使われている。 
    4848 
    49  * 実際には、これらの数字には以下のような意味がある: 
     49実際には、これらの数字には以下のような意味がある: 
    5050||l0.xとl0.y || データの読み込みのポインタ初期値|| 
    5151||l0.z          || そのポインタのインクリメント用|| 
     
    5555 
    5656= ループについて = 
    57  * CALでのループの実現には、色々な方法があるが、ここでは"whileloop"文を利用する。これは、"whileloop"と"endloop"に挟まれた命令列を永久に実行するという命令文である。よって、無限ループを終わらせる処理を自前で書く必要がある。必要な部分だけを抜き出すと以下のようなCALプログラムがループのひな形となる: 
     57CALでのループの実現には、色々な方法があるが、ここでは"whileloop"文を利用する。これは、"whileloop"と"endloop"に挟まれた命令列を永久に実行するという命令文である。よって、無限ループを終わらせる処理を自前で書く必要がある。必要な部分だけを抜き出すと以下のようなCALプログラムがループのひな形となる: 
    5858{{{ 
    5959whileloop 
     
    6363endloop 
    6464}}} 
    65  ここで、"r4.x"をループカウンタとして、"r4.w"をループの上限値として使っている。これはC言語で書くと以下のような処理に相当する: 
     65 
     66ここで、"r4.x"をループカウンタとして、"r4.w"をループの上限値として使っている。これはC言語で書くと以下のような処理に相当する: 
    6667{{{ 
    6768while(1) { 
     
    7172}}} 
    7273 
    73  *  "ige"の行は、"r4.x"と"r4.w"の大小を比較して、"r4.x >= r4.w"が成り立っているならば、"r2.x"にTRUEがセットされる(詳しくはil.pdfの43ページを参照のこと。以下同様)。 
     74"ige"の行は、r4.xとr4.wの大小を比較して、"r4.x >= r4.w"が成り立っているならば、r2.xにTRUEがセットされる(詳しくはil.pdfの43ページを参照のこと。以下同様)。 
    7475 
    75  * "break_logicalnz r2.x"は、"r2.x"が0でないならば、今のループを終了する。TRUEは0ではないので、"ige"でTRUEがセットされていたら、このループが終了する。この2命令を合わせて、C言語のほうのif文に相当することになる。 
     76"break_logicalnz r2.x"は、r2.xが0でないならば、今のループを終了する。TRUEは0ではないので、"ige"でTRUEがセットされていたら、このループが終了する。この2命令を合わせて、C言語のほうのif文に相当することになる。 
    7677 
    77  * "iadd"は、単純に整数の加算である。"r4.z"は"1"として初期化されているので、"r4.x"をインクリメントすることになる。 
     78"iadd"文は、単純に整数の加算である。r4.zは整数値1として初期化されているので、r4.xをインクリメントすることになる。 
    7879 
    7980= 配列データのランダムアクセス = 
    80  * これまで、データの読み込みには、"dcl_input_interp"命令で得たindex pair("v0.xy")を使ってきた。これは、kernelプログラムが実行される論理プロセッサごとに、別々のindex pairが割り振られる。実際には、index pairの値は(0.0, 0.0)からはじまる浮動小数点値の組である(と思われる)。 
     81これまで、データの読み込みには、"dcl_input_interp"命令で得たindex pair("v0.xy")を使ってきた。これは、kernelプログラムが実行される論理プロセッサごとに、別々のindex pairが割り振られる。実際には、index pairの値は(0.0, 0.0)からはじまる浮動小数点値の組である(と思われる)。 
    8182  
    82  * 今のプログラムにおいて、id=0のリソースは、CAL_FORMAT_FLOAT_1で1次元のメモリとして宣言したので、C言語の配列で書くとすると、"float array[256]"と同等である。このリソースの任意の場所をCALのプログラムで読み込むためには、"sample_resource"命令に適切なindex pairを与えればよい。具体的には以下のようになる: 
     83今のプログラムにおいて、id=0のリソースは、CAL_FORMAT_FLOAT_1で1次元のメモリとして宣言したので、C言語の配列で書くとすると、"float array[256]"と同等である。このリソースの任意の場所をCALのプログラムで読み込むためには、"sample_resource"命令に適切なindex pairを与えればよい。具体的には以下のようになる: 
    8384{{{ 
    8485array[0] -> (0.0, 0.0) 
     
    9192 実際には、今の場合リソースが1次元として宣言されているのでyのほうの値は無視される。 
    9293 
    93  * "prog.il"の16行では、"r1.x"がindexとして指定されている。この値は8行で0.0に初期化されており、19行で1.0が足されている。よって、このループで19行が実行される度に、"r1.x"は0.0,1.0, 2.0...と増加していくことになる。結果として、"r1.x"で指定された場所から、"r0.x"にid=0のリソースから値が読み込まれることになる。読み込まれた値は、17行において"r3.x"と足し合わされ、合計が計算される。 
     94"prog.il"の16行では、r1.xがindexとして指定されている。この値は8行で0.0に初期化されており、19行で1.0が足されている。よって、このループで19行が実行される度に、r1.xは0.0,1.0, 2.0...と増加していくことになる。結果として、r1.xで指定された場所から、r0.xにid=0のリソースから値が読み込まれることになる。読み込まれた値は、17行において"r3.x"と足し合わされ、合計が計算される。 
    9495 
    9596= 動作のまとめ = 
    96  * 以上の動作をまとめると、このkernelプログラムは「id=0のリソースを先頭から順番に10回読み込んでその合計を計算する」という動作になる。 
     97以上の動作をまとめると、このkernelプログラムは「id=0のリソースを先頭から順番に10回読み込んでその合計を計算する」という動作になる。 
    9798 
    98  * なお、ループ回数の10は、"prog.il"の6行のw成分で指定されている。今、"hello.cpp"では、この入力メモリに1から256までの値をいれているので、計算結果は55となる。 
     99なお、ループ回数の10は、"prog.il"の6行のw成分で指定されている。今、"hello.cpp"では、この入力メモリに1から256までの値をいれているので、計算結果は55となる。 
    99100 
    100101= 課題 =