2011年2月28日月曜日

ドット積(内積)を求める

CUDA BY EXAMPLE 5.3.1節。 N次元ベクトル2つの内積を、256スレッドからなる複数のブロックを使って求める。 ブロック数は32個とするが、Nが小さい場合には必要な数だけのブロックを起動する。 各ブロックは、担当の部分の要素の積の和を求めて結果をCPUに返す。 よって32個以下の値がCPUに返ってくる。この総和(が内積である)をCPUは求めて表示する。

各スレッドの仕事は以下のようになっている。

  • Nがちょうど256*32である場合、256*32個のスレッドそれぞれは1つのベクトル要素対を担当し、その積を求める。
  • N=256*32*2である場合、ひとつのスレッドは、あるベクトル要素対と、そこから256*32個後ろのベクトル要素対の2つを担当し、それぞれの積の総和を求める。一般にN=256*32*Mの場合、各スレッドはM個のベクトル要素対の積の総和を求める。
  • Nが256*32よりも小さい場合、スレッド数が足りる(つまりN以上となる)最小の数だけのブロックを起動する。

Nがぴったり256の倍数でない場合の処理は常套句の while (tid < N) で行われている。

各スレッドが自分の担当するところの積の和を求めたら、ブロック内で縮約して総和を求め、CPUに返す(カーネルの仮引数c、mainから見ると(dev_)partial_c)。CPUは返された32個(あるいはそれ以下)の値の総和を求める。

68ページにある最小倍数回りの分かりにくい部分は、こう読むといい:「データ要素がN個なので、ドット積を計算するのに必要なスレッドはN個である。スレッド数が256個*32ブロックでは多すぎる場合には、threadsPerBlock (=256) の倍数であってかつN以上であるような最も小さい個数のブロックを用いればよい。これはベクトルの和でも取り上げた。今回の場合は、(N+threadsPerBlock-1))/threadsPerBlock を計算することで、そのようなブロック数を求める。」

ビジー状態を保つはよく分からない。