使用CUDA共享内存改进全局访问模式

使用CUDA共享内存改进全局访问模式,cuda,shared-memory,Cuda,Shared Memory,我使用以下内核来获得一组向量的大小: __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

我使用以下内核来获得一组向量的大小:

__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);
    }
}

然而,当
n%blockDim.x!=0
,需要事先知道最大
块DIM
,并在使用
n=1024
进行测试时,为
out[i>255]
生成不正确的结果。我应该如何最好地解决这个问题?

我认为这可以解决
out[I>255]
问题:

__shared__ double shIn[3*BLOCKDIM];

const uint blockStart = blockIdx.x * blockDim.x;

invec[0*blockDim.x+threadIdx.x] = in[ blockStart*3 + 0*blockDim.x + threadIdx.x];
invec[1*blockDim.x+threadIdx.x] = in[ blockStart*3 + 1*blockDim.x + threadIdx.x];
invec[2*blockDim.x+threadIdx.x] = in[ blockStart*3 + 2*blockDim.x + threadIdx.x];
__syncthreads();

double x = shIn[3*threadIdx.x];
double y = shIn[3*threadIdx.x+1];
double z = shIn[3*threadIdx.x+2];

out[blockStart+threadIdx.x] = sqrt(x*x + y*y + z*z);
至于
n%blockDim.x!=0
我建议用0填充输入/输出数组,以符合要求

如果您不喜欢
BLOCKDIM
宏,请使用
extern\uuuuuu shArr[]
进行探索,然后将第三个参数传递给内核配置:

norm_v2<<<gridSize,blockSize,dynShMem>>>(...)
它基本上将任何数组视为
int
-s的数组,并将数据从一个位置复制到另一个位置。如果仅使用64位类型,则可能需要将基础的
int
类型替换为
double
-s或
long-long int

然后可以将复制行替换为:

memCopy(invec, in+blockStart*3, min(blockDim.x, n-blockStart));

我认为这可以解决
out[I>255]
问题:

__shared__ double shIn[3*BLOCKDIM];

const uint blockStart = blockIdx.x * blockDim.x;

invec[0*blockDim.x+threadIdx.x] = in[ blockStart*3 + 0*blockDim.x + threadIdx.x];
invec[1*blockDim.x+threadIdx.x] = in[ blockStart*3 + 1*blockDim.x + threadIdx.x];
invec[2*blockDim.x+threadIdx.x] = in[ blockStart*3 + 2*blockDim.x + threadIdx.x];
__syncthreads();

double x = shIn[3*threadIdx.x];
double y = shIn[3*threadIdx.x+1];
double z = shIn[3*threadIdx.x+2];

out[blockStart+threadIdx.x] = sqrt(x*x + y*y + z*z);
至于
n%blockDim.x!=0
我建议用0填充输入/输出数组,以符合要求

如果您不喜欢
BLOCKDIM
宏,请使用
extern\uuuuuu shArr[]
进行探索,然后将第三个参数传递给内核配置:

norm_v2<<<gridSize,blockSize,dynShMem>>>(...)
它基本上将任何数组视为
int
-s的数组,并将数据从一个位置复制到另一个位置。如果仅使用64位类型,则可能需要将基础的
int
类型替换为
double
-s或
long-long int

然后可以将复制行替换为:

memCopy(invec, in+blockStart*3, min(blockDim.x, n-blockStart));