我有一个CUDA内核对局部变量(在寄存器中)进行一些计算,在计算之后,它的值被写入全局数组p
:
__global__ void dd( float* p, int dimX, int dimY, int dimZ )
{
int
i = blockIdx.x*blockDim.x + threadIdx.x,
j = blockIdx.y*blockDim.y + threadIdx.y,
k = blockIdx.z*blockDim.z + threadIdx.z,
idx = j*dimX*dimY + j*dimX +i;
if (i >= dimX || j >= dimY || k >= dimZ)
{
return;
}
float val = 0;
val = SomeComputationOnVal();
p[idx ]= val;
__syncthreads();
}
不幸的是,这个函数执行得很慢。
但是,如果我这样做,它的运行速度非常快:
__global__ void dd( float* p, int dimX, int dimY, int dimZ )
{
int
i = blockIdx.x*blockDim.x + threadIdx.x,
j = blockIdx.y*blockDim.y + threadIdx.y,
k = blockIdx.z*blockDim.z + threadIdx.z,
idx = j*dimX*dimY + j*dimX +i;
if (i >= dimX || j >= dimY || k >= dimZ)
{
return;
}
float val = 0;
//val = SomeComputationOnVal();
p[idx ]= val;
__syncthreads();
}
如果我这样做,它也会非常快地运行:
__global__ void dd( float* p, int dimX, int dimY, int dimZ )
{
int
i = blockIdx.x*blockDim.x + threadIdx.x,
j = blockIdx.y*blockDim.y + threadIdx.y,
k = blockIdx.z*blockDim.z + threadIdx.z,
idx = j*dimX*dimY + j*dimX +i;
if (i >= dimX || j >= dimY || k >= dimZ)
{
return;
}
float val = 0;
val = SomeComputationOnVal();
// p[idx ]= val;
__syncthreads();
}
所以我很困惑,不知道如何解决这个问题。我已经使用过NSight,但没有发现访问冲突。
以下是我启动内核的方法(dimX:924; dimY:16:dimZ:1120):
dim3
blockSize(8,16,2),
gridSize(dimX/blockSize.x+1,dimY/blockSize.y, dimZ/blockSize.z);
float* dev_p; cudaMalloc((void**)&dev_p, dimX*dimY*dimZ*sizeof(float));
dd<<<gridSize, blockSize>>>( dev_p,dimX,dimY,dimZ);
有人可以请一些指示吗?因为它对我没有多大意义。 val的所有计算都很快,最后一步是将val
移动到p
。 p
从不参与计算,它只显示一次。那为什么这么慢?
计算基本上是512×512矩阵的循环。我说的是相当多的计算量。
答案 0 :(得分:0)
您在SomeComputationOnVal中执行的计算非常昂贵。每个线程读取至少1MB的数据,这些数据不在缓存中(或者在一个小部分中最好是L2,如果k在很小的范围内变化),总计大约16 TB的数据。即使在高端GPU上,也至少需要2分钟才能运行。更不用提任何可能减缓这种情况的事了。
您的函数不会在全局内存中写入任何数据,也没有边界效应。如果不使用输出,编译器可能会决定优化方法调用。
因此,第二和第三个没有进行计算的情况非常快。在gpu内存上写入64 MB,使用coesced线程非常快(毫秒范围)。
您可以验证生成的ptx以查看代码是否已优化。在nvcc中使用--keep选项并搜索ptx文件。