C++ CUDA:使用共享内存的全局线程索引赢得';行不通

C++ CUDA:使用共享内存的全局线程索引赢得';行不通,c++,pointers,memory,cuda,shared,C++,Pointers,Memory,Cuda,Shared,有人能解释一下,当我的共享内存指针数组TMS在第0个索引之外的某个索引(发生在最后一行)被访问时,为什么我的内核不工作?如果在最后一行中使用TMS[0],则一切正常。当我将TMS[0]更改为任何其他索引时,我得到一个CUDA意外错误。假设一个块上有64个线程 #include <stdio.h> #include <stdlib.h> #include "cuda.h" #include <cuda_runtime.h> #include <curand

有人能解释一下,当我的共享内存指针数组TMS在第0个索引之外的某个索引(发生在最后一行)被访问时,为什么我的内核不工作?如果在最后一行中使用TMS[0],则一切正常。当我将TMS[0]更改为任何其他索引时,我得到一个CUDA意外错误。假设一个块上有64个线程

#include <stdio.h>
#include <stdlib.h>
#include "cuda.h"
#include <cuda_runtime.h>
#include <curand_kernel.h>

__global__ void myKern(float *masterForces)
{
    int globalIdx = ...// set global thread id

    volatile __shared__ float uniques[64];

    {
        uniques[globalIDx] = 0;
    }

    __syncthreads();


    volatile __shared__ float *TMS[64]; 

    {
       TMS[globalIdx] = (&uniques[globalIdx]);
    }

    __syncthreads();

    masterForces[globalIdx] = *TMS[1];
}
#包括
#包括
#包括“cuda.h”
#包括
#包括
__全局无效myKern(浮动*主力)
{
int globalIdx=…//设置全局线程id
易失性共享浮点唯一性[64];
{
uniques[globalIDx]=0;
}
__同步线程();
易失性共享浮点*TMS[64];
{
TMS[globalIdx]=(&uniques[globalIdx]);
}
__同步线程();
masterForces[globalIdx]=*TMS[1];
}
如果你好奇的话,请参考原文:(你真的不需要看这个来解决我的问题)

#包括
#包括
#包括“cuda.h”
#包括“curand.h”
#包括
#包括“math.h”
#包括
#包括
__全局无效myKern(常量浮点*跨矩阵,常量整数*指针矩阵,浮点*主控力,常量双*随机数,常量整数r_max)
{
int globalIdx=((blockIdx.x+(blockIdx.y*gridDim.x))*(blockDim.x*blockDim.y))+(threadIdx.x+(threadIdx.y*blockDim.x));
易失性-共享-浮点唯一性[51];
uniques[0]=跨矩阵[0];uniques[1]=跨矩阵[1];uniques[2]=跨矩阵[2];//1
uniques[3]=跨矩阵[3];uniques[4]=跨矩阵[4];uniques[5]=跨矩阵[12];//2
uniques[6]=跨矩阵[14];uniques[7]=跨矩阵[15];uniques[8]=跨矩阵[24];//3
uniques[9]=跨矩阵[26];uniques[10]=跨矩阵[27];uniques[11]=跨矩阵[28];//4
uniques[12]=跨矩阵[40];uniques[13]=跨矩阵[50];uniques[14]=跨矩阵[60];//5
uniques[15]=跨矩阵[62];uniques[16]=跨矩阵[146];uniques[17]=跨矩阵[156];//6
uniques[18]=跨矩阵[158];uniques[19]=跨矩阵[168];uniques[20]=跨矩阵[170];//7
uniques[21]=跨矩阵[172];uniques[22]=跨矩阵[184];uniques[23]=跨矩阵[290];//8
uniques[24]=跨矩阵[300];uniques[25]=跨矩阵[302];uniques[26]=跨矩阵[312];//9
uniques[27]=跨矩阵[314];uniques[28]=跨矩阵[316];uniques[29]=跨矩阵[328];//10
uniques[30]=跨矩阵[1010];uniques[31]=跨矩阵[1020];uniques[32]=跨矩阵[1022];//11
uniques[33]=跨矩阵[1032];uniques[34]=跨矩阵[1034];uniques[35]=跨矩阵[1036];//12
uniques[36]=跨矩阵[1048];uniques[37]=跨矩阵[1154];uniques[38]=跨矩阵[1164];//13
uniques[39]=跨矩阵[1166];uniques[40]=跨矩阵[1176];uniques[41]=跨矩阵[1178];//14
uniques[42]=跨矩阵[1180];uniques[43]=跨矩阵[1192];uniques[44]=跨矩阵[2018];//15
uniques[45]=跨矩阵[2028];uniques[46]=跨矩阵[2030];uniques[47]=跨矩阵[2040];//16
uniques[48]=跨矩阵[2042];uniques[49]=跨矩阵[2044];uniques[50]=跨矩阵[2056];//17
__同步线程();
易失性共享浮点数*TMS[2592];

对于(int t=0;t假设全局线程索引(
globalIdx
)实际上是一个全局线程索引,例如:

int globalIdx = threadIdx.x+blockDim.x*blockIdx.x; // e.g. for 1D grid/threadblock
如果全局线程索引超过63,则无法索引到64项共享内存数组:

    uniques[globalIDx] = 0;

如果只使用线程索引:

    uniques[threadIdx.x] = 0;
类似地,在代码的其他地方,假设每个块有64个线程,那么至少在索引到共享内存数组方面应该是可以的

下面是一个充分发挥作用的示例:

$ cat t463.cu
#include <stdio.h>
#define DSIZE 128
#define nTPB 64
__global__ void myKern(float *masterForces)
{
    int globalIdx = threadIdx.x+blockDim.x*blockIdx.x;

    volatile __shared__ float uniques[nTPB];

    {
        uniques[threadIdx.x] = 0;
    }

    __syncthreads();


    volatile __shared__ float *TMS[nTPB];

    {
       TMS[threadIdx.x] = &(uniques[threadIdx.x]);
    }

    __syncthreads();

    masterForces[globalIdx] = *TMS[1];
}

int main(){

  float *d_data, *h_data;
  h_data=(float *)malloc(DSIZE*sizeof(float));
  cudaMalloc(&d_data, DSIZE*sizeof(float));
  for (int i = 0; i< DSIZE; i++)
    h_data[i] = 1.0f;
  cudaMemcpy(d_data, h_data, DSIZE*sizeof(float), cudaMemcpyHostToDevice);
  myKern<<<DSIZE/nTPB, nTPB>>>(d_data);
  cudaMemcpy(h_data, d_data, DSIZE*sizeof(float), cudaMemcpyDeviceToHost);
  for (int i = 0; i<DSIZE; i++)
    if (h_data[i] != 0.0f) {printf("mismatch at %d, was: %f should be: %f\n", i, h_data[i], 0.0f); return 1;}
  printf("Success\n");
  return 0;
}
$ nvcc -arch=sm_20 -o t463 t463.cu
$ cuda-memcheck ./t463
========= CUDA-MEMCHECK
Success
========= ERROR SUMMARY: 0 errors
$
$cat t463.cu
#包括
#定义DSIZE 128
#定义nTPB 64
__全局无效myKern(浮动*主力)
{
int globalIdx=threadIdx.x+blockDim.x*blockIdx.x;
易失性共享浮点数[nTPB];
{
uniques[threadIdx.x]=0;
}
__同步线程();
易失性共享浮点数*TMS[nTPB];
{
TMS[threadIdx.x]=&(uniques[threadIdx.x]);
}
__同步线程();
masterForces[globalIdx]=*TMS[1];
}
int main(){
浮点*d_数据,*h_数据;
h_数据=(浮动*)malloc(DSIZE*sizeof(浮动));
cudaMalloc(&d_数据,DSIZE*sizeof(float));
对于(int i=0;i对于(int i=0;i您的示例代码不应该给出任何错误,正如Robert Crovella所证明的那样。我查看了您的原始代码,发现第一个“for”导致括号未对齐循环。祝你好运…

请发布一个完整的代码来演示错误。因此,这是意料之中的事。在共享内存数组中使用全局索引作为偏移量通常不是一个好兆头……好吧,但我警告你,这相当复杂。上面的代码应该能够捕获问题。目标是提供最短的代码来演示问题,就像我提供了一个演示解决方案的简短代码一样。请注意这一点,以备将来发布时使用。是的,这需要您的努力,但我们期待这一点,它将帮助其他人帮助您。很抱歉,回复太晚,我正在遛狗。糟糕的回复,谢谢罗伯特。我只做一件事不明白。为什么globalIdx不能工作?如果我有64个线程,globalIdx应该永远不会超过63个。你能帮我理解一下吗。
globalIdx
如果你将整个内核限制在64个线程,那么它可以工作。为了证明这一点,只需将我代码中的
\define DSIZE
更改为
64
,然后你就可以使用
globalIdx
无论我在哪里
threadIdx.x
(这样做的净效果是只启动一个块),但如果整个内核启动(即网格)涉及64个以上的线程,则不能使用全局索引索引到共享内存数组中。只要转到第二个块,全局索引就会停止
    uniques[threadIdx.x] = 0;
$ cat t463.cu
#include <stdio.h>
#define DSIZE 128
#define nTPB 64
__global__ void myKern(float *masterForces)
{
    int globalIdx = threadIdx.x+blockDim.x*blockIdx.x;

    volatile __shared__ float uniques[nTPB];

    {
        uniques[threadIdx.x] = 0;
    }

    __syncthreads();


    volatile __shared__ float *TMS[nTPB];

    {
       TMS[threadIdx.x] = &(uniques[threadIdx.x]);
    }

    __syncthreads();

    masterForces[globalIdx] = *TMS[1];
}

int main(){

  float *d_data, *h_data;
  h_data=(float *)malloc(DSIZE*sizeof(float));
  cudaMalloc(&d_data, DSIZE*sizeof(float));
  for (int i = 0; i< DSIZE; i++)
    h_data[i] = 1.0f;
  cudaMemcpy(d_data, h_data, DSIZE*sizeof(float), cudaMemcpyHostToDevice);
  myKern<<<DSIZE/nTPB, nTPB>>>(d_data);
  cudaMemcpy(h_data, d_data, DSIZE*sizeof(float), cudaMemcpyDeviceToHost);
  for (int i = 0; i<DSIZE; i++)
    if (h_data[i] != 0.0f) {printf("mismatch at %d, was: %f should be: %f\n", i, h_data[i], 0.0f); return 1;}
  printf("Success\n");
  return 0;
}
$ nvcc -arch=sm_20 -o t463 t463.cu
$ cuda-memcheck ./t463
========= CUDA-MEMCHECK
Success
========= ERROR SUMMARY: 0 errors
$