用于多维数组处理的 DirectCompute 多线程性能(线程和线程组)

DirectCompute multithreading performance (threads and thread groups) for multidimensional array processing

我知道 Disptach(x, y, z) 将定义实例化多少组线程,而 numthreads(n, m, p) 给出每组的大小。

结合在一起,Dispatch 和 numthreads 给出线程总数。我也明白dispatch arguments是用来给每个线程传递参数的。

问题:

1) I组J线程和J组I线程有性能差异吗?两个选项提供相同数量的线程。

2) 假设我必须处理一个只有在运行时才知道大小的二维矩阵,使用 Dispatch(DimX, DimY, 1) 和 numthreads(1, 1, 1) 很方便,这样我就有了在每个矩阵元素的线程上,其位置由 DTid.xy 给出。由于 numthreads() 参数是在编译时确定的,我如何才能获得处理维度不是线程组大小的倍数且在编译时未知的矩阵所需的确切线程数?

1) 是的,存在(或可能存在)性能差异,具体取决于实际数量和使用的硬件!

GPU(通常)包含多个所谓的 "waves" 线程。这些 waves 以类似 SIMD 的方式工作(wave 中的所有线程总是同时执行相同的操作)。每个 wave 的确切线程数是特定于供应商的,但通常是 32(我知道的所有 NVidia GPU)或 64(大多数 AMD GPU)。

一组线程可以分配给多个wave。但是,单个 wave 只能执行同一组的线程。因此,如果每组的线程数不是硬件 wave 大小的倍数,则 wave 中有一些线程是 "idling"(它们实际上与其他线程做同样的事情,但不是允许写入内存),因此您可以 "loosing" 使用更多线程获得的性能。

2) 您很可能 select 一个适合您的硬件的线程数(64 将是一个很好的默认值,因为它也是 32 的倍数),并使用分支将线程标记为"inactive" 位于矩阵之外(您可以使用常量缓冲区将 matrix/data 的大小传递给着色器)。由于这些非活动线程根本没有做任何事情,硬件可以简单地将它们屏蔽为 "read-only"(类似于如果每组线程数小于波浪大小时它们将如何处理),这是相当便宜的。如果一个wave中的所有线程都被标记为inactive,硬件甚至可以选择完全跳过这个wave的工作,这将是最优的。

您还可以使用填充来确保您的 matrix/data 始终是每组线程数的倍数,例如使用零或单位矩阵或其他。但是,这是否可以完成取决于应用程序,我认为在大多数情况下分支会一样快 - 如果不是更快的话。