Multithreading 是否可以将共享内存的一部分专用于每个线程?

Multithreading 是否可以将共享内存的一部分专用于每个线程?,multithreading,cuda,gpgpu,Multithreading,Cuda,Gpgpu,我正在Ubuntu18.04上使用CUDA 10.1,我想知道是否有可能为每个线程分配一部分共享内存。我的意思是,比方说,我希望每个线程都有一个相对较大的私有数组,该数组不适合放入寄存器,将该数组放入共享内存将引入竞争条件,因为块上的每个线程都可以访问它。因此,我非常感兴趣的是使用共享内存的一部分作为“寄存器”,这样我就可以避免竞争条件。我知道这会限制我在SM中可以使用的线程数量,从而限制我的占用率,但在我的情况下,这种折衷是值得的。 感谢您的帮助 否,不可能将共享内存分配(静态或动态)专用于特

我正在Ubuntu18.04上使用CUDA 10.1,我想知道是否有可能为每个线程分配一部分共享内存。我的意思是,比方说,我希望每个线程都有一个相对较大的私有数组,该数组不适合放入寄存器,将该数组放入共享内存将引入竞争条件,因为块上的每个线程都可以访问它。因此,我非常感兴趣的是使用共享内存的一部分作为“寄存器”,这样我就可以避免竞争条件。我知道这会限制我在SM中可以使用的线程数量,从而限制我的占用率,但在我的情况下,这种折衷是值得的。 感谢您的帮助

否,不可能将共享内存分配(静态或动态)专用于特定线程。共享内存只有块作用域

然而,完全可以设计一种索引方案,其中块内的线程专门使用块作用域共享内存分配中的唯一位置。例如:

template<int nthreads, int words_per_thread>
__global__
void kernel(..)
{
    __shared__ int buffer[nthreads * words_per_thread];

    int* localbuff = &buffer[threadIdx.x * words_per_thread];

    // localbuff is now safely indexed from [0] to [words_per_thread-1]

}
模板
__全球的__
无效内核(…)
{
__共享整型缓冲区[n线程*每个线程的字数];
int*localbuff=&buffer[threadIdx.x*每个线程的单词数];
//localbuff现在可以安全地从[0]索引到[words\u per\u thread-1]
}
另一种可能的方法如下:

#include <stdio.h>
template<typename T>
class sr_
{
  T *sp;
  public:
  __device__
  sr_(T *_sd) { sp = _sd;}
  __device__
  T &operator[](int idx){return sp[blockDim.x*idx+threadIdx.x];}
};
// for statically allocated shared memory
#define SREG(size,type,block_size) \
  __shared__ type SREG_sdata[size*block_size]; \
  typedef type SREG_type; \
  sr_<SREG_type> sreg(SREG_sdata);
// for dynamically allocated shared memory
#define DSREG(type) \
  __shared__ type SREG_sdata[]; \
  typedef type SREG_type; \
  sr_<SREG_type> sreg(SREG_sdata);

const int BS = 8;

__global__ void k2(){
  SREG(8,float,BS)
  sreg[0] = 1.0f;
  printf("%f\n", sreg[0]);
}

int main(){

  k2<<<1,BS>>>();
  cudaDeviceSynchronize();
}
#包括
模板
高级船员_
{
T*sp;
公众:
__装置__
sr_u(T*sd){sp=sd;}
__装置__
运算符[](int-idx){return sp[blockDim.x*idx+threadIdx.x];}
};
//用于静态分配的共享内存
#定义SREG(大小、类型、块大小)\
__共享类型SREG_sdata[大小*块大小]\
类型定义类型SREG_类型\
sr_usreg(sreg_sdata);
//用于动态分配共享内存
#定义DSREG(类型)\
__共享类型SREG_sdata[]\
类型定义类型SREG_类型\
sr_usreg(sreg_sdata);
常数int BS=8;
__全局无效k2(){
SREG(8,浮动,BS)
sreg[0]=1.0f;
printf(“%f\n”,sreg[0]);
}
int main(){
k2();
cudaDeviceSynchronize();
}
它的好处是,一个线程不可能索引到另一个线程的空间,并且不会有任何库冲突。注意,这不会处理所有用例。例如,如果同一个模块中有多个内核使用不同的数据类型作为共享内存,则必须对其进行修改