在CUDA中访问全局内存很慢

时间:2016-05-24 15:14:32

标签: memory cuda gpu gpgpu

我有一个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移动到pp从不参与计算,它只显示一次。那为什么这么慢?

计算基本上是512×512矩阵的循环。我说的是相当多的计算量。

1 个答案:

答案 0 :(得分:0)

您在SomeComputationOnVal中执行的计算非常昂贵。每个线程读取至少1MB的数据,这些数据不在缓存中(或者在一个小部分中最好是L2,如果k在很小的范围内变化),总计大约16 TB的数据。即使在高端GPU上,也至少需要2分钟才能运行。更不用提任何可能减缓这种情况的事了。

您的函数不会在全局内存中写入任何数据,也没有边界效应。如果不使用输出,编译器可能会决定优化方法调用。

因此,第二和第三个没有进行计算的情况非常快。在gpu内存上写入64 MB,使用coesced线程非常快(毫秒范围)。

您可以验证生成的ptx以查看代码是否已优化。在nvcc中使用--keep选项并搜索ptx文件。