AMD Stream SDK

コメント欄で、Vista で走らせる方法を教えて頂きました。
WindowsVista x64 SP1 + RADEON HD 4850 を使用しています。

AMD Stream SDK

(1) AMD Stream SDK 1.01.0_beta を install
(2) Folding@home GPU2 6.20 を install
(3) C:\Program Files (x86)\AMD\AMD CAL 1.01.1_beta\lib\xp32
  内の amdcalcl.dll, amdcalrt.dll の代わりに、
  C:\Users\<USER>\AppData\Roaming\Folding@home-gpu
  に入っている dll を使う。

(2) の注意点
すでに NVIDIA GPU 上で Folding@home を走らせたことがある場合は下記の手順で
 1. Folding@home を uninstall
 2. C:\Users\<USER>\AppData\Roaming\Folding@home-gpu を削除
 3. \C:\Program Files (x86)\Folding@home\Folding@home-gpu を削除
 4. Folding@home を再び install

例えば C:\Program Files (x86)\AMD\AMD CAL 1.01.1_beta\bin\xp32 に
入っているサンプルは、上記 dll と同じ場所にあれば実行できます。
サンプルのコンパイルは VisualStudio2008 でも大丈夫でした。

CAL の使い方は
C:\Program Files (x86)\AMD\AMD CAL 1.01.1_beta\doc
の ProgrammingGuide.pdf に従います。

GPU 上で走らせるプログラム kernel はほぼシェーダー相当の機能を持っています。
入出力用のリソースを確保し、context に割り当てて、シェーダー内のレジスタに渡します。

最初少々はまったのは PixelShader 相当だということ。
入力リソースは dcl_input に渡すわけではなく、あくまで texture のように
リソース扱いで sampler 経由で読み込みます。
4096 vector 以下なら constant buffer を使うことも可能です。

dcl_input で受け取るのはラスタライザの補間パラメータ相当です。
CAL の場合はこれを自分自身の ID と見なすことが出来ます。
いわゆるシステム値の SV_Position で、出力位置を指しています。

dcl_input の詳しい説明が載ってませんが、ほぼ次のような宣言の仕方で
使われています。

dcl_input_position v0.xy
dcl_input_interp(linear) v0.xy

例えば実行時の CALdomain が 0,0 から 128,128 までなら
0.5~127.5 のように 0.5 offset された値が入ります。
上の 2つの宣言の違いは特にありませんでした。

CALdomain は出力範囲の指定に相当します。RenderTarget の書き込み範囲です。
実行するプログラムの数や dcl_input のパラメータにも影響します。

シェーダーと違うのは、自由に読み書きできる共有メモリ Global Buffer を持っていることです。
Global Buffer (g[]) は Constant Buffer (cb[]) と同じように、命令内で直接
アドレッシング出来ます。書き込みも出来ます。

mad g[0], r0, g[1], r1

o0~ を使ったストリーム出力と違い書き込み制限がありません。

マニュアルに詳細が書かれていませんが、実際に試したところ 4850/4870 では
最大 2048 vector 使用することが出来ました。

常に 128bit = 4要素単位となるため、8192 float 相当 = 32KByte 分と考えられます。
特に同期などの仕組みがないので、同じ Global Buffer への書き込みが発生した場合、
値は不定となるようです。

実際に Global Buffer から値を読んで Global Buffer に書き込むプログラムを
走らせてみるとわかります。
同じタイミングで実行されているスレッドでは同じ初期値が読み込まれます。
実行スレッド数を増やしていくと、そのうち書き込んだ値を読み出している
スレッドも含まれるようになります。

実行はほぼ ID 順ですが、リソース読みだしを行うと順番が崩れてきます。
リソースアクセス待ち間のスケジューリングのためと考えられます。

DirectX11 の Compute Shader では同期アクセスがサポートされるらしいので、
同じメモリに書き込みを行って合計値を求めるような使い方ができるみたいですが
CAL ではおそらく出来ません。

RADEON HD 4850
##calDeviceGetInfo()
target=5  RV770
maxResource1DWidth=8192
maxResource2DWidth=8192
maxResource2DHeight=8192

##calDeviceGetAttribs()
target=5
localRAM=512
uncachedRemoteRAM=2047
cachedRemoteRAM=2047
engineClock=625
memoryClock=337
wavefrontSize=64
numberOfSIMD=10
doublePrecision=1
memExport=1

関連エントリ
AMD Stream Computing