C fnd全局函数允许的最大块/线程数

C fnd全局函数允许的最大块/线程数,c,cuda,C,Cuda,这似乎是一个简单的问题,但我在任何地方都找不到答案。 我有一个全局函数,可以这样调用: func<<<nbBlocks,nbThreadByBlock, nbBytesOfSharedMmy>>>(args); func(args); 如果我理解正确,我对nbThreadByBlock的使用量永远不能超过1024,但是我如何动态地知道我的函数func和我的GPU允许的nbThreadByBlock的最大值是多少 如果我的func函数使用了更多的局部变量,那

这似乎是一个简单的问题,但我在任何地方都找不到答案。 我有一个全局函数,可以这样调用:

func<<<nbBlocks,nbThreadByBlock, nbBytesOfSharedMmy>>>(args);
func(args);
如果我理解正确,我对nbThreadByBlock的使用量永远不能超过1024,但是我如何动态地知道我的函数
func
和我的GPU允许的
nbThreadByBlock
的最大值是多少

如果我的
func
函数使用了更多的局部变量,那么每个块的最大线程数就会减少,这种想法正确吗

关于我可以使用的区块总数,有上限吗?我在想,如果我放的积木比可能的多,它们会被按顺序处理,是真的吗

谢谢

下面是一段代码

cudaDeviceProp deviceProp;
cudaGetDeviceProperties(&deviceProp, 0); //assuming current device ID is 0
将设备的属性收集到
deviceProp
中。如您所见,成功调用
cudaGetDeviceProperties
后,您将能够访问具有所需设备属性的
deviceProp
成员。例如,
deviceProp.maxThreadsPerMultiProcessor
表示每个多处理器的最大线程数,
deviceProp.maxThreadsPerBlock
表示每个块的最大线程数,等等

每个块的适当线程数和调用函数的总块数主要取决于设备属性和程序。您调用的每个块都占用SM的一部分。多少取决于块请求的资源:线程、寄存器和共享内存。
考虑这个例子。假设您的设备SMs最多可以有2048个线程、48 KB的共享内存和64 KB的寄存器。如果块需要512个线程,同时使用SM可用的所有共享内存和寄存器,则SM中不可能有具有相同特征的另一个块。因此,由于不能使用2048减去512个潜在SM线程,您可以将实现的最大占用率降低到25%。现在,如果将块中的线程数增加到1024个,就可以使用相同数量的寄存器和共享内存,那么占用率就翻了一番,达到了50%

通常不建议使用大量块。GPU将新块调度到可用SMs。如果所有SMs都被占用,它将对该块进行排队,直到SM有足够的空闲资源用于该块。调度新块会给GPU带来开销(尽管很小)。最好在找到最佳块大小后,计算(或配置)SM上的块占用率,然后调用占用所有GPU SMs的块数。如果需要更多的块,可以重用已完成其工作的块的线程。
例如转换

GPU_kernel<<<1024,512>>>();
进入

GPU内核();
其中

__global__ void GPU_kernel(void){

    unsigned int tid = (blockIdx.x * blockDim.x) + threadIdx.x;
    //rest of code
}
__global__ void GPU_kernel(void){

    unsigned int tid = (blockIdx.x * blockDim.x) + threadIdx.x;
    for (; tid < 1024*512; tid +=  blockIdx.x* gridDim.x ) {
        //rest of code
    }
} 
\uuuuu全局\uuuuuu无效GPU内核(无效){
unsigned int tid=(blockIdx.x*blockDim.x)+threadIdx.x;
对于(;tid<1024*512;tid+=blockIdx.x*gridDim.x){
//代码的其余部分
}
} 
通常会导致更好的性能

还要注意,在上面的代码中,我没有包括正确的CUDA错误检查。请应用您自己的方法来处理可能的错误。指示

__global__ void GPU_kernel(void){

    unsigned int tid = (blockIdx.x * blockDim.x) + threadIdx.x;
    for (; tid < 1024*512; tid +=  blockIdx.x* gridDim.x ) {
        //rest of code
    }
}