Indexing CUDA中的每个内核调用是否保证唯一的线程Id? 我最近开始与CUDA合作,在C++、java和Python上有多线程、多进程编码的经验。

Indexing CUDA中的每个内核调用是否保证唯一的线程Id? 我最近开始与CUDA合作,在C++、java和Python上有多线程、多进程编码的经验。,indexing,cuda,nvidia,pycuda,Indexing,Cuda,Nvidia,Pycuda,在PyCuda中,我看到这样的示例代码 ker=SourceModule(“”) __全局\无效标量\乘法\内核(浮点*outvec,浮点标量,浮点*vec) { int i=threadIdx.x; outvec[i]=标量*vec[i]; } """) 线程id本身似乎参与了代码的逻辑。然后问题是,是否有足够的线程ID覆盖我的整个数组(显然,我需要对其进行索引以访问其中的所有元素),以及如果我更改数组的大小会发生什么情况 索引是否总是在0和N之间?在CUDA中,线程id仅在每个所谓的线程块

在PyCuda中,我看到这样的示例代码

ker=SourceModule(“”)
__全局\无效标量\乘法\内核(浮点*outvec,浮点标量,浮点*vec)
{
int i=threadIdx.x;
outvec[i]=标量*vec[i];
}
""")
线程id本身似乎参与了代码的逻辑。然后问题是,是否有足够的线程ID覆盖我的整个数组(显然,我需要对其进行索引以访问其中的所有元素),以及如果我更改数组的大小会发生什么情况


索引是否总是在0和N之间?

在CUDA中,线程id仅在每个所谓的线程块中是唯一的,这意味着,您的示例内核只在一个块工作的情况下做正确的事情。在早期的示例中,这可能是为了让您更容易理解这些想法,但就性能而言,这通常是一件非常糟糕的事情:

对于一个块,您只能在GPU中使用多个流式多处理器(SMs)中的一个,甚至SM也只能在等待时有足够的并行工作时隐藏内存访问延迟

如果内核不包含循环,每个线程可以计算多个元素,那么单线程块也会限制线程的数量,从而限制问题的大小

内核执行在层次上是很强的:为了简单起见,我们将自己限制在一维索引上,内核在所谓的
gridDim.x
线程块网格上执行,每个线程块包含
blockDim.x
线程,每个线程块由
threadIdx.x
编号,而每个块都通过
blockIdx.x
进行编号

要获取线程的唯一ID(理想情况下使用硬件从数组加载元素),必须使用
blockIdx.x*blockDim.x+threadIdx.x
。若每个线程都要计算多个元素,那个么您可以使用以下形式的循环

for(inti=blockIdx.x*blockDim.x+threadIdx.x;i

这称为网格跨步循环,因为
gridDim.x*blockDim.x
是在内核上工作的所有线程数。不同的步幅(特别是让线程处理连续元素:步幅=1)可能会起作用,但由于非理想的内存访问模式,速度会慢得多。

在CUDA中,线程id仅在每个所谓的线程块中是唯一的,这意味着示例内核只在一个块工作的情况下做正确的事情。在早期的示例中,这可能是为了让您更容易理解这些想法,但就性能而言,这通常是一件非常糟糕的事情:

对于一个块,您只能在GPU中使用多个流式多处理器(SMs)中的一个,甚至SM也只能在等待时有足够的并行工作时隐藏内存访问延迟

如果内核不包含循环,每个线程可以计算多个元素,那么单线程块也会限制线程的数量,从而限制问题的大小

内核执行在层次上是很强的:为了简单起见,我们将自己限制在一维索引上,内核在所谓的
gridDim.x
线程块网格上执行,每个线程块包含
blockDim.x
线程,每个线程块由
threadIdx.x
编号,而每个块都通过
blockIdx.x
进行编号

要获取线程的唯一ID(理想情况下使用硬件从数组加载元素),必须使用
blockIdx.x*blockDim.x+threadIdx.x
。若每个线程都要计算多个元素,那个么您可以使用以下形式的循环

for(inti=blockIdx.x*blockDim.x+threadIdx.x;i

这称为网格跨步循环,因为
gridDim.x*blockDim.x
是在内核上工作的所有线程数。不同的步幅(特别是线程处理连续元素:步幅=1)可能会起作用,但由于非理想的内存访问模式,速度会慢得多。

简言之否。在《编程指南》的前几页中有大量的文档说明了这一点。在《编程指南》的前几页中有大量的文档说明了这一点