金属计算着色器线程组和线程执行宽度

Dee*_*rma 3 threadgroup compute-shader ios metal metalkit

有人可以简单地解释一下 Metal 计算着色器中线程组的概念以及其他术语(例如 SIMD 组、threadExecutionWidth(波前))吗?我阅读了文档,但更加困惑。例如,如果我有一个 1024x1024 图像,我可以有多少个线程组,如何将线程映射到每个像素,有多少个线程可以并发运行,等等?我找不到描述计算着色器和这些概念的 WWDC 视频。

Mat*_*ans 7

线程组是一组一起工作来解决某个(子)问题的线程。线程组中最多可以有5121024个线程(取决于您使用的设备)。

threadExecutionWidth是所使用的 SIMD 组的大小。它通常是32,这意味着每个 SIMD 组32中都有线程。为了获得最佳性能,线程组中的线程数应该是 的倍数threadExecutionWidth。(这确实是其他人所说的波前或扭曲。)

如果您有一张1024x1024图像,并且希望一个线程处理一个像素,并且最大线程组大小为512,那么您可以创建一个由大小为 的线程组(即)1024x1024组成的线程网格。32x6432x16512

但实际上,您可以按照自己的意愿划分线程。您还可以有一个2x1024大小为 的线程组网格512x1,或者其他。

  • GPU 硬件分为多个 SIMD 组。如果 threadExecutionWidth 为 32,maxThreadsPerThreadgroup 为 512,则意味着硬件中有 512/32=16 个 SIMD 组,每个 SIMD 组一次可以运行 32 个线程。GPU 将决定将哪一组 32 个线程调度到哪个 SIMD 组中——作为开发人员,您无法控制这一点。苹果并未公布实际的硬件细节,因此 GPU 的具体工作原理主要是猜测。 (4认同)
  • 至于“我们可以安全地假设像素将以 512 块为单位进行串行处理吗?”。首先,*您*作为开发人员确定这个线程网格是什么样子以及每个线程应该做什么。GPU 并不关心,它只是启动您请求的线程。其次,GPU 可以按任意顺序启动这些线程,但它始终会以 threadExecutionWidth 组的形式启动,因为它必须始终一次运行整个 SIMD 组。即使您使用 1 个线程,它仍然运行整个 SIMD 组,只是丢弃其他 31 个线程的结果。 (2认同)