如果有5个块,每个10个线程,我们必须对长度为50的数组执行一些操作,我的第一个块将作用于前10个数组元素,然后第二个块的线程将作用于接下来的10个元素等等。是这种情况吗?
我问这是因为
我有2个图像,我发现逐个像素的差异,其中差异高于某个阈值,使像素1为0,然后显示这个二进制图像。现在也有一些很小的差异,我想忽略。我逐块地对像素值进行求和,如果某个块的数量小于某个阈值,我将其设为0.但是现在有一些额外的位置也会消失,因为那些块位于块的角落。 我该怎么办?
答案 0 :(得分:1)
内存访问模式可以自由编程,因此这完全取决于您的代码。
每个线程都有单独的threadIdx and blockIdx变量,然后可以根据需要使用它来计算数组索引或地址。
然而,让连续线程访问内存中的连续位置as this is more efficient通常是个好主意。
当硬件将线程分组到32个线程的warps时,最好使块大小至少为32的倍数,这样就不会有资源被闲置。由于一些资源(寄存器)一次分配给2个warp,因此64的倍数的块大小可能更有效。
CUDA C Programming Guide是一个开始阅读的好地方,尤其是关于编程模型的章节。 CUDA C Best Practices Guide提供了有关如何调整代码以获得最佳效果的更多信息。
答案 1 :(得分:0)
我认为你对CUDA的运作方式有点困惑。 CUDA不是自动矢量化器。让我解释一下:
假设您有一张图片A
和B
,并想要在这两者之间执行逐像素差异,从而生成图片C
。在高度专业化的DSL中,您可以编写C = A-B
,并让语言自动找出所需的所有索引。在这种语言中,有必要问一下索引是如何完成的。
但这不是CUDA中发生的事情。在这里,你提供索引。您可能知道,在启动内核时,会生成几个块,每个块包含多个线程。每个线程都由内置值threadIdx
和blockIdx
标识。您必须使用这些来索引您的图像。例如:
int globalIndex = blockIdx.x*blockDim.x + threadIdx.x;
C[globalIndex] = A[globalIndex] - B[globalIndex];
在这样的设置中,连续线程访问图像的相邻像素。您可以对其进行不同的索引,例如:
int globalIndex = blockIdx.x*blockDim.x + threadIdx.x;
if (globalIndex % 32 == 0)
C[globalIndex/32] = A[globalIndex/32] - B[globalIndex/32];
现在每个第32个线程访问相邻的像素。其他线程什么都不做。它会慢大约32倍,但这是你的选择。你可以控制它。
当然这些是最简单的例子。您可能希望使用2D图像。您可能想要检查这些图像的边界。您可能想要启动2D内核。这些都是CUDA语言无法为您做出的选择。
因此,您的问题没有明确的答案。 你是将线程分配给数组中的单元格。这将是你选择它。
无法控制的是执行顺序。可能是线程256在线程0之前执行。但这是另一个主题,您在问题中没有提到。