【问题标题】:Using of shared memory not showing desired result使用共享内存未显示预期结果
【发布时间】:2014-10-20 14:01:50
【问题描述】:

我正在尝试学习共享内存的用法,以提高性能。在这里,我试图将全局内存复制到共享内存。但是当我有单个块(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&lt;&lt;&lt;n_blocks,block_size,n*sizeof(int)&gt;&gt;&gt;(d_d, n); 中的第三个参数是什么 内核调用呢?它是否为整个块或线程分配共享内存。

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

【问题讨论】:

    标签: cuda shared-memory


    【解决方案1】:

    在您的静态共享内存分配代码中,您遇到了三个问题:

    1. 静态分配的共享内存的大小应该符合块大小,而不是输入数组的大小,
    2. 您应该使用本地线程索引而不是全局线程索引来索引共享内存;
    3. 没有数组越界检查。

    动态共享内存分配代码与上面的 #2 和 #3 有相同的问题,而且您使用本地线程索引而不是全局索引来索引全局内存。您可以使用第三个参数来指定要分配的共享内存的大小。特别是,您应该分配256 ints 的数量,即与块大小相关,类似于静态共享内存分配情况。

    这是完整的工作代码:

    /********************/
    /* 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]); }
    
    }
    

    【讨论】:

    • 当我有大约 100,000 作为 n=100,000 的较大 n 值时,它会给出 -ve 值。它是什么?这是因为共享内存有限吗??
    • 如果我使用两个具有共享内存的内核会怎样。那样的话,一个块可用的内存被划分了??
    • @user3929491 我已经通过添加CUDA error checking 编辑了代码。请使用此版本并报告它发出的任何运行时错误。对于n = 100000,上面的代码对我来说似乎运行良好。关于第二个问题,对于每个内核,每个块的可用共享内存量始终相同,它没有被划分。
    • @user3929491 您的代码无法处理较大的n 值的最可能原因是您正在执行ad 的静态分配。尝试将int a[n], d[n]; 更改为int* a = (int*) malloc(n*sizeof(int));int* d = (int*) malloc(n*sizeof(int));。我已经相应地编辑了我的帖子。
    • 对于 s[0] 处的第二个块,复制了 d[256] 的值,这似乎覆盖了第一个块的值。那么它最后不会对 d[0] 和 d[256] 的输出进行任何更改。他们没有相同的价值吗??
    猜你喜欢
    • 2021-01-05
    • 2011-10-02
    • 2019-04-05
    • 2022-08-14
    • 2021-04-14
    • 2020-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多