c++ GPGPU:用于1D线程索引的CUDA内核配置-线程、块、共享内存和寄存器

mklgxw1f  于 2023-05-20  发布在  其他
关注(0)|答案(1)|浏览(111)

假设我有N个任务,其中每个任务可以由GPU上的单个线程执行。还假设N = GPU上的线程的数量。

**问题1:**以下方式是否适合启动 maximum 大小的1D内核?GPU上存在的所有N个线程都将执行该工作吗?

cudaDeviceProp  theProps;

dim3 mygrid(theProps.maxGridSize[0], 1, 1);
dim3 myblocks(theProps.maxThreadsDim[0], 1, 1);

mykernel<<<mygrid, myblocks>>>(...);

问题2:cudaDeviceProp::maxThreadsPerBlock相对于cudaDeviceProp::maxThreadsDim[0]的性质是什么?它们有什么不同?cudaDeviceProp::maxThreadsPerBlock可以代替上面的cudaDeviceProp::maxThreadsDim[0]吗?
**问题3:**假设我想在块中的线程之间平均分配块的共享内存,并且我希望每个线程都有最多的共享内存。然后我应该最大化块的数量,并最小化每个块的线程数量,对吗?
**问题4:**确认一下(在查看了SO的相关问题后),在上述线性(1D)网格/块方案中,全局唯一线程索引为unsigned int tid = blockIdx.x * blockDim.x + threadIdx.x。对吧?

s2j5cfk0

s2j5cfk01#

建议每个问题只问一个问题。有各种各样的问题使任何人都很难给予一个完整的答案。所以这并不是一个真正的辅导服务。您应该利用现有的documentationwebinars,当然还有许多其他可用的资源。
下面是启动最大大小的1D内核的合适方法吗?GPU上存在的所有N个线程都将执行该工作吗?
这当然是可能的,所有启动的线程(假设它被称为N)将可用于执行工作,它将启动一个最大(1D)大小的网格。但你为什么要这么做?大多数cuda编程方法并不以此为目标。网格应根据算法调整大小。如果1D网格大小似乎是一个限制,您可以通过在内核中执行循环来处理每个线程的多个数据元素,或者启动一个2D网格来绕过1D网格限制。对cc3.x设备的限制已扩展。
与cudaDeviceProp::maxThreadsDim[0]相关的cudaDeviceProp::maxThreadsPerBlock属性是什么?它们有什么不同?cudaDeviceProp::maxThreadsPerBlock是否可以替换上面的cudaDeviceProp::maxThreadsDim[0]?
第一个是对多维块中的总线程的限制(即,threads_xthreads_ythreads_z)。第二个是对第一维(x)大小的限制。对于1D螺纹块,它们是可互换的,因为y和z维度是1。对于多维块,多维限制的存在是为了通知用户,例如maxThreadsDim[0]*maxThreadsDim[1]*maxThreadsDim[2]的线程块是不法律的的。
假设我想在块中的线程之间平均分配块的共享内存,并且我想让每个线程都有最多的共享内存。然后我应该最大化块的数量,并最小化每个块的线程数量,对吗?
我再次对这种方法表示怀疑。但是,理论上每个线程可能的最大共享内存字节数将由最小线程数的线程块来实现。然而,允许线程块使用所有可用的共享存储器可能导致一次只有一个线程块可以驻留在SM上。这可能对占用具有负面影响,这可能对性能具有负面影响。有许多有用的建议来选择线程块大小,以最大限度地提高性能。我不能在这里全部总结。但是我们希望选择线程块大小作为线程束大小的倍数,我们通常希望每个线程块有多个线程束,并且所有其他条件都相同,我们希望启用最大占用率(这与可以驻留在SM上的线程块的数量有关)。
只是为了确认(在回顾关于SO的相关问题之后),在上面的线性(1D)网格/块方案中,全局唯一线程索引是unsigned int tid = blockIdx.x * blockDim.x + threadIdx. x。对吧?
是的,对于一维线程块和网格结构,这一行将给予一个全局唯一的线程ID:

unsigned int tid = blockIdx.x * blockDim.x + threadIdx.x;

相关问题