我有以下內核得到一堆向量幅度:使用CUDA共享內存來改善全球訪問模式
__global__ void norm_v1(double *in, double *out, int n)
{
const uint i = blockIdx.x * blockDim.x + threadIdx.x;
if (i < n)
{
double x = in[3*i], y = in[3*i+1], z = in[3*i+2];
out[i] = sqrt(x*x + y*y + z*z);
}
}
但是由於in
包裝作爲[x0,y0,z0,...,xn,yn,zn]
它表明與探查表現不佳32%的全球負載效率。將數據重新包裝爲[x0, x1, ..., xn, y0, y1, ..., yn, z0, z1, ..., zn]
可以大大提高工作效率(其中x
,y
和z
的偏移量會相應改變)。運行時間縮短,效率高達100%。
但是,這種包裝對我的應用來說根本不實用。因此,我希望調查共享內存的使用。我的想法是,塊中的每個線程都可以從全局內存中複製三個值(分開爲blockDim.x
) - 從而產生合併訪問。在最大blockDim.x = 256
假設我想出了:
#define BLOCKDIM 256
__global__ void norm_v2(double *in, double *out, int n)
{
__shared__ double invec[3*BLOCKDIM];
const uint i = blockIdx.x * blockDim.x + threadIdx.x;
invec[0*BLOCKDIM + threadIdx.x] = in[0*BLOCKDIM+i];
invec[1*BLOCKDIM + threadIdx.x] = in[1*BLOCKDIM+i];
invec[2*BLOCKDIM + threadIdx.x] = in[2*BLOCKDIM+i];
__syncthreads();
if (i < n)
{
double x = invec[3*threadIdx.x];
double y = invec[3*threadIdx.x+1];
double z = invec[3*threadIdx.x+2];
out[i] = sqrt(x*x + y*y + z*z);
}
}
然而,這顯然是不足的時候n % blockDim.x != 0
,需要預先知道的最大blockDim
,當與n = 1024
測試out[i > 255]
產生不正確的結果。我應該如何最好地解決這個問題?