GPU对于一个工作负载非常大的计算着色器来说,合适的线程尺寸是什么?




我正在制作一个统一的高度图侵蚀计算着色器,其中地图上的每个点分别被侵蚀。这对于小地图来说工作得很好,但我正在做的项目需要4096x4096的地图。这意味着需要模拟4096^2 = 16777216点。默认线程尺寸为[64,1,1],这将创建262144个线程组,远远超过允许的65535的限制。

我的问题是:
我可以简单地提高线程尺寸吗?当我这样做时,我必须考虑哪些性能方面的问题?是否有可能简单地运行着色器多次,不同范围的高度图坐标?

这是我第一次使用着色器。我在网上看到的教程很快就深入到gpu硬件规格,所以我没有从中学到太多。

使用每个工作组的64x64线程,您可以Dispatch64x64工作组做您需要的事情:请记住,64x64线程将为您调度的每个工作组调用,因此您将有64x64 work groups x 64x64 threads=4096 workgroups x 4096 threads执行。

computeShader.Dispatch(computeShader.FindKernel("kernel"), 64, 64, 1);
[numthreads(64, 64, 1)]
void kernel(uint3 id : SV_DispatchThreadID)
{
// ...
// 0 <= id.x < 4096
// 0 <= id.y < 4096
}

至于对性能的影响,一般的回答是"试试看!":使用不同大小的线程和工作组运行内核。结果可能因您的计算和硬件而异。

但是,如果您需要绕过65535限制,您可以使用DispatchIndirect。基本上,它与Dispatch相同,但参数是通过ComputeBuffer传递的。

ComputeBuffer argsBuffer = new ComputeBuffer(3, sizeof(uint), ComputeBufferType.IndirectArguments);
uint[] args = { 64, 64, 1 }; // work groups
argsBuffer.SetData(args);
computeShader.DispatchIndirect(computeShader.FindKernel("kernel"), argsBuffer);

Ps:在GPU上工作需要理解它的架构,因为(1)你在一个较低的层次上工作,接近硬件,你工作的许多功能实际上是硬件实现的(例如纹理);(2)你想让你的程序获得最好的性能(例如,充分利用块,翘曲和缓存…);)

相关内容

  • 没有找到相关文章

最新更新