0

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

结合在一起,Dispatch 和 numthreads 给出了线程的总数。我还理解调度参数用于将参数传递给每个线程。

问题:

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

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

4

1 回答 1

1

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

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

一组线程可以分布到多个波。但是,单个 wave 只能执行同一组的线程。因此,如果您每组的线程数不是硬件波形大小的倍数,则波形中有一些线程“空闲”(它们实际上与其他线程做相同的事情,但不允许写入内存),因此您正在“失去”使用更多线程数可以获得的性能。

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

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

于 2019-09-25T18:50:07.333 回答