GPUプログラミング
CUDAで、GPUカーネル(__global__を付けた関数)が計算した結果を、CPU側のプログラムで受け取る方法として正しいものはどれか。
- Aカーネルの戻り値(return)で、全スレッドの結果がまとめてCPUへ返る
- Bカーネルが結果をGPUのメモリ上の配列に書き込み、CPU側はカーネルの終了後にその配列をCPUのメモリへコピーして(またはユニファイドメモリを読んで)受け取る
- C各スレッドがprintfで出力した値を、CPU側のプログラムが変数として読み取る
答えと解説を見る
正解:B. カーネルが結果をGPUのメモリ上の配列に書き込み、CPU側はカーネルの終了後にその配列をCPUのメモリへコピーして(またはユニファイドメモリを読んで)受け取る
GPUカーネルは多数のスレッドが同時に実行するので、1つの戻り値で結果を返すことはできず、CUDAでは__global__の関数の戻り値の型はvoidと決められています。CPU側はGPUのメモリに配列を確保してそのポインタを引数で渡し、各スレッドは担当する要素に結果を書き込みます。カーネルの起動は非同期なので、カーネルが終わってからcudaMemcpyなどで配列をCPU側へコピーします(同じストリームなら、コピーは前のカーネルの終了を待ちます)。カーネルの中のprintfは表示のためのデバッグの手段で、その値をプログラムで受け取ることはできません。
- A. __global__の関数の戻り値はvoidと決められています。
- B. 正しい。結果はメモリを通して受け取ります。
- C. printfは表示するだけで、出力をプログラムの値としては使えません。