Линейное индексирование с использованием Compute Shader - PullRequest
0 голосов
/ 03 мая 2018

Я использую вычислительные шейдеры для некоторых вещей. Я создаю входной буфер (который является одномерным) определенной длины, а затем вызываю диспетчеризацию по 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, но некоторые повторяются, и я не понимаю, почему ...

1 Ответ

0 голосов
/ 05 мая 2018

Количество измерений в группировке потоков используется скорее для удобства, чем для оптимизации. Под капотом все встряхнется, чтобы быть примерно одинаковым. Так что для 1D буфера вам будет не хуже, если использовать что-то вроде

[numthreads(64, 1, 1)]
void Reconstruction(uint3 dispatchThreadID : SV_DispatchThreadID)
{
    int idx = dispatchThreadID.x;
    // ... etc ...
}

чем то, что у вас есть выше. Вы также получаете дополнительное преимущество, заключающееся в том, что вы выполняете меньше вычислений в своем шейдере, поскольку вы автоматически получаете правильные индексы, передаваемые через параметр SV_.

Единственная оптимизация, которую вы должны иметь в виду, заключается в том, что общее количество потоков в группе в идеале должно быть кратным 64. Это связано с тем, что на аппаратном уровне графические процессоры AMD обычно работают с "волнами" из 64 потоков в время. NVidia - это (если я правильно помню) 32, которая все еще работает. Если вы используете, скажем, 32, то вы получите 50% использования на AMD, что не круто.

...