使用共享内存未显示所需结果

时间:2014-08-27 05:25:07

标签: cuda shared-memory

我正在尝试学习共享内存的使用,以提高性能。在这里我试图将全局内存复制到共享内存。但是当我有单个块(256个线程)时,它会给出结果,并且有超过1个块,它会产生随机结果。

#include <cuda.h>
#include <stdio.h>

__global__ void staticReverse(int *d, int n)
{
  __shared__ int s[400];

  int t = blockIdx.x * blockDim.x + threadIdx.x;
  d[t] = d[t]*d[t];
  s[t] =d[t];

  __syncthreads();

  d[t] = s[t];  
}


__global__ void dynamicReverse(int *d, int n)
{
  extern __shared__ int s[];
  int t = threadIdx.x;

  s[t] = d[t]*d[t];
  __syncthreads();
  d[t] = s[t];
}

int main(void)
{
  const int n = 400;
  int a[n], d[n];

  for (int i = 0; i < n; i++)
  {
    a[i] = i; 
  }

  int *d_d;
  cudaMalloc(&d_d, n * sizeof(int)); 

  // run version with static shared memory
  int block_size = 256;
  int n_blocks = n/block_size + (n%block_size == 0 ? 0:1);
  cudaMemcpy(d_d, a, n*sizeof(int), cudaMemcpyHostToDevice);
  staticReverse<<<n_blocks,block_size>>>(d_d, n);
  cudaMemcpy(d, d_d, n*sizeof(int), cudaMemcpyDeviceToHost);
  for (int i = 0; i < n; i++) 
  {
    printf("%d\n",d[i]);
  }
}

1)dynamicReverse<<<n_blocks,block_size,n*sizeof(int)>>>(d_d, n);中的第三个参数是什么 核心呼叫吗?它为整个块或线程分配共享内存。

2)如果我在计算能力5.0中每个多处理器需要超过64kb的共享内存,我需要做什么?

1 个答案:

答案 0 :(得分:3)

在静态共享内存分配代码中,您有三个问题:

  1. 静态分配的共享内存的大小应符合块大小,而不是输入数组的大小,
  2. 您应该使用本地线程索引来索引共享内存,而不是全局内存;
  3. 你没有超出界限的数组。
  4. 动态共享内存分配代码具有与上述相同的问题#2和#3,以及您使用本地线程索引而不是全局索引全局内存的事实。您可以使用第三个参数指定要分配的共享内存的大小。特别是,您应该分配一定数量的256 int s,即与块大小相关,类似于静态共享内存分配情况。

    以下是完整的工作代码:

    /********************/
    /* CUDA ERROR CHECK */
    /********************/
    #define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
    inline void gpuAssert(cudaError_t code, char *file, int line, bool abort=true)
    {
        if (code != cudaSuccess) 
        {
            fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
            if (abort) exit(code);
        }
    }
    
    /***********************************/
    /* SHARED MEMORY STATIC ALLOCATION */
    /***********************************/
    #include <cuda.h>
    #include <stdio.h>
    
    __global__ void staticReverse(int *d, int n)
    {
        __shared__ int s[256];
    
        int t = blockIdx.x * blockDim.x + threadIdx.x;
    
        if (t < n) {
            d[t] = d[t]*d[t];
            s[threadIdx.x] =d[t];
    
            __syncthreads();
    
            d[t] = s[threadIdx.x];
        }
    }
    
    
    /************************************/
    /* SHARED MEMORY DYNAMIC ALLOCATION */
    /************************************/
    __global__ void dynamicReverse(int *d, int n)
    {
        extern __shared__ int s[];
        int t = blockIdx.x * blockDim.x + threadIdx.x;
    
        if (t < n) {
            s[threadIdx.x] = d[t]*d[t];
            __syncthreads();
            d[t] = s[threadIdx.x];
        }
    }
    
    int main(void)
    {
        const int n = 400;
    
        int* a = (int*) malloc(n*sizeof(int));
        int* d = (int*) malloc(n*sizeof(int));
    
        for (int i = 0; i < n; i++) { a[i] = i; }
    
        int *d_d; gpuErrchk(cudaMalloc(&d_d, n * sizeof(int))); 
    
        // run version with static shared memory
        int block_size = 256;
        int n_blocks = n/block_size + (n%block_size == 0 ? 0:1);
    
        gpuErrchk(cudaMemcpy(d_d, a, n*sizeof(int), cudaMemcpyHostToDevice));
        //staticReverse<<<n_blocks,block_size>>>(d_d, n);
        dynamicReverse<<<n_blocks,block_size,256*sizeof(int)>>>(d_d, n);
        gpuErrchk(cudaPeekAtLastError());
        gpuErrchk(cudaDeviceSynchronize());
    
        gpuErrchk(cudaMemcpy(d, d_d, n*sizeof(int), cudaMemcpyDeviceToHost));
    
        for (int i = 0; i < n; i++) { printf("%d\n",d[i]); }
    
    }