私はベクトル・ドット積(A×B)を実行するCudaカーネルに取り組んでいます。私は各ベクトルの長さが32の倍数(32,64、...)であると仮定し、ブロックサイズを配列の長さと等しくなるように定義しました。ブロック内の各スレッドは、Aの1つの要素にBの対応する要素(スレッドi ==> psum = A [i] xB [i])を乗算します。乗算後、ワープシャッフル技術を使って減算を行い、すべての乗算の合計を計算する次の関数を使用しました。任意の長さの配列を減らすためのワープ・シャッフル
__inline__ __device__
float warpReduceSum(float val) {
int warpSize =32;
for (int offset = warpSize/2; offset > 0; offset /= 2)
val += __shfl_down(val, offset);
return val;
}
__inline__ __device__
float blockReduceSum(float val) {
static __shared__ int shared[32]; // Shared mem for 32 partial sums
int lane = threadIdx.x % warpSize;
int wid = threadIdx.x/warpSize;
val = warpReduceSum(val); // Each warp performs partial reduction
if (lane==0)
shared[wid]=val; // Write reduced value to shared memory
__syncthreads(); // Wait for all partial reductions
//read from shared memory only if that warp existed
val = (threadIdx.x < blockDim.x/warpSize) ? shared[lane] : 0;
if (wid==0)
val = warpReduceSum(val); // Final reduce within first warp
return val;
}
psumは2つの要素をスレッドで乗算したものです。単にblockReduceSum(psum)を呼び出します。
配列の長さが32の倍数でない場合、このアプローチは機能しません。だから私の質問は、このコードを変更して任意の長さにすることができますか?配列の長さが32の倍数でない場合、複数のワープに複数の配列に属する要素があるため、不可能ですか?