我有以下内核来获得一堆向量的大小:
__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
out[i > 255]
n = 1024