cuda:共享内存总是有用吗?

时间:2013-11-15 10:00:24

标签: c cuda shared-memory

当我阅读编程指南时,我感觉共享内存将始终提高性能,但似乎没有。 我有两个功能:

const int Ntimes=1;

__global__ void testgl(float *A, float *C, int numElements){

    int ti = threadIdx.x;
    int b0 = blockDim.x*blockIdx.x;

    if (b0+ti < numElements){
        for(int i=0;i<Ntimes;i++){
            A[b0+ti]=A[b0+ti]*A[b0+ti]*10-2*A[b0+ti]+1;
        }
        C[b0+ti] = A[b0+ti]*A[b0+ti];
    }
}


__global__ void testsh(float *A, float *C, int numElements){

    int ti = threadIdx.x;
    int b0 = blockDim.x*blockIdx.x;

    __shared__ float a[1024];

    if (b0+ti < numElements){
        a[ti]=A[b0+ti];
    }

    __syncthreads();

    if (b0+ti < numElements){
        for(int i=0;i<Ntimes;i++){
            a[ti]=a[ti]*a[ti]*10-2*a[ti]+1;
        }
        C[b0+ti] = a[ti]*a[ti];
    }
}

int main(void){

    int numElements = 500000;
    size_t size = numElements * sizeof(float);

    // Allocate the host input
    float *h_A = (float *)malloc(size);
    float *h_B = (float *)malloc(size);

    // Allocate the host output
    float *h_C = (float *)malloc(size);
    float *h_D = (float *)malloc(size);


    // Initialize the host input
    for (int i = 0; i < numElements; i++){
        h_A[i] = rand()/(float)RAND_MAX;
        h_B[i] = h_A[i];
    }

    // Allocate the device input
    float *d_A = NULL; cudaMalloc((void **)&d_A, size);
    float *d_B = NULL; cudaMalloc((void **)&d_B, size);
    float *d_C = NULL; cudaMalloc((void **)&d_C, size);
    float *d_D = NULL; cudaMalloc((void **)&d_D, size);


    //Copy to Device
    cudaMemcpy(d_A, h_A, size, cudaMemcpyHostToDevice);  
    cudaMemcpy(d_B, h_B, size, cudaMemcpyHostToDevice);


    // Launch the Vector Add CUDA Kernel
    int threadsPerBlock = 1024;
    int blocksPerGrid =(numElements + threadsPerBlock - 1) / threadsPerBlock;

    testgl<<<blocksPerGrid, threadsPerBlock>>>(d_A, d_C, numElements);

    testsh<<<blocksPerGrid, threadsPerBlock>>>(d_B, d_D, numElements);

    // Copy the device resultto the host 
    cudaMemcpy(h_C, d_C, size, cudaMemcpyDeviceToHost);
    cudaMemcpy(h_D, d_D, size, cudaMemcpyDeviceToHost);


    // Free device global memory
    cudaFree(d_A);
    cudaFree(d_B);
    cudaFree(d_C);
    cudaFree(d_D);

    // Free host memory
    free(h_A);
    free(h_B);
    free(h_C);
    free(h_D);

    // Reset the device and exit
    cudaDeviceReset();

    return 0;
}

如果Ntimes设置为1,则testgl的成本为49us,testsh的成本为97us。 如果Ntimes设置为100,则testgl的成本为9.7ms,testsh的成本为8.9ms。

我不知道为什么它会超过100倍。

所以看起来共享内存只有在我们想要在设备上做很多事情时才有帮助,是吗?

此处使用的卡片是 GTX680

提前致谢。

1 个答案:

答案 0 :(得分:1)

共享内存将始终提高性能

这不是真的。这取决于算法。如果你在内核中有一个完美合并的内存访问,并且只是一次它可能无法帮助你访问全局内存。但是如果你正在实现假设一个矩阵乘法,你需要保持部分和,那么它将是有用的。

如果你在内核中多次访问相同的内存位置也会有所帮助,因为在这种情况下,共享内存延迟比全局内存少100倍因为它的片上内存。

当您分析内核带宽受限时,如果有使用共享内存的范围并提高性能,则可以考虑使用它。它也是更好的策略,检查占用计算器,以检查共享内存的使用是否会影响占用率。

共享内存仅在我们想要在设备中执行大量操作时才有帮助

部分是的。当我们想要在设备中做很多事情时,共享内存会有所帮助。

在上面的内核中,由于您在内核中不止一次访问全局内存,因此它应该有所帮助。如果您可以提供完整的复制器来分析代码,将会很有帮助。了解您正在运行的卡详细信息也很有帮助。