使用计算着色器的线性索引
Linear Indexing using Compute Shader
我正在使用计算着色器来做一些事情。我创建了一个特定长度的输入缓冲区(一维),然后在 x 和 y 上调用调度以优化计算时间。但是我在访问索引时遇到问题。可能是什么问题?
double size = Math.Ceiling(Math.Sqrt(input.pattern.Length));
shader.Start((int)Math.Ceiling(size/32), (int)Math.Ceiling(size / 32), 1);
并且在 hlsl 代码中...
[numthreads(32, 32, 1)]
void Reconstruction(uint3 dispatchThreadID : SV_DispatchThreadID)
{
int idx = dispatchThreadID.y * size + dispatchThreadID.x;
if (idx > rayCount) { return; }
我打印了 idx 但有些重复了,我不明白为什么...
线程分组中的维数更多是为了方便而不是优化。在引擎盖下,一切都会变得差不多。所以对于 1D 缓冲区,使用类似
的东西不会更糟
[numthreads(64, 1, 1)]
void Reconstruction(uint3 dispatchThreadID : SV_DispatchThreadID)
{
int idx = dispatchThreadID.x;
// ... etc ...
}
比上面的要好。您还可以获得额外的好处,即您最终会在着色器中进行更少的计算,因为您将自动获得通过 SV_
参数传入的正确索引。
您应该记住的唯一优化是一个组中的线程总数理想情况下应该是 64 的倍数。这是因为在硬件级别,AMD GPU 通常使用 "waves"一次 64 个线程。 NVidia 是(如果我没记错的话)32,仍然有效。如果您使用(比如说)32,那么您将在 AMD 上获得 50% 的利用率,这并不酷。
我正在使用计算着色器来做一些事情。我创建了一个特定长度的输入缓冲区(一维),然后在 x 和 y 上调用调度以优化计算时间。但是我在访问索引时遇到问题。可能是什么问题?
double size = Math.Ceiling(Math.Sqrt(input.pattern.Length));
shader.Start((int)Math.Ceiling(size/32), (int)Math.Ceiling(size / 32), 1);
并且在 hlsl 代码中...
[numthreads(32, 32, 1)]
void Reconstruction(uint3 dispatchThreadID : SV_DispatchThreadID)
{
int idx = dispatchThreadID.y * size + dispatchThreadID.x;
if (idx > rayCount) { return; }
我打印了 idx 但有些重复了,我不明白为什么...
线程分组中的维数更多是为了方便而不是优化。在引擎盖下,一切都会变得差不多。所以对于 1D 缓冲区,使用类似
的东西不会更糟[numthreads(64, 1, 1)]
void Reconstruction(uint3 dispatchThreadID : SV_DispatchThreadID)
{
int idx = dispatchThreadID.x;
// ... etc ...
}
比上面的要好。您还可以获得额外的好处,即您最终会在着色器中进行更少的计算,因为您将自动获得通过 SV_
参数传入的正确索引。
您应该记住的唯一优化是一个组中的线程总数理想情况下应该是 64 的倍数。这是因为在硬件级别,AMD GPU 通常使用 "waves"一次 64 个线程。 NVidia 是(如果我没记错的话)32,仍然有效。如果您使用(比如说)32,那么您将在 AMD 上获得 50% 的利用率,这并不酷。