【发布时间】:2016-11-23 01:14:06
【问题描述】:
我正在研究执行矢量点积 (A x B) 的 Cuda 内核。我假设每个向量的长度是 32 (32,64, ...) 的倍数,并将块大小定义为等于数组的长度。块中的每个线程将 A 的一个元素乘以 B 的相应元素(线程 i ==>psum = A[i]xB[i])。在乘法之后,我使用了以下函数,这些函数使用了 warp shuffle 技术来执行归约并计算所有乘法的总和。
__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;
}
我只是调用 blockReduceSum(psum) ,其中 psum 是两个元素乘以一个线程。
当数组的长度不是 32 的倍数时,这种方法不起作用,所以我的问题是,我们可以更改此代码,使其也适用于任何长度吗?还是不可能,因为如果数组的长度不是 32 的倍数,则某些扭曲的元素属于多个数组?
【问题讨论】: