Производительность многопоточности DirectCompute (потоки и группы потоков) для обработки многомерных массивов - PullRequest
0 голосов
/ 24 сентября 2019

Я понимаю, что Disptach (x, y, z) будет определять, сколько групп потоков создается, а numthreads (n, m, p) дает размер каждой группы.

Объединенные вместе, Dispatch иnumthreads дает общее количество потоков.Я также понял, что аргументы диспетчеризации используются для передачи параметров каждому потоку.

Вопросы:

1) Есть ли разница в производительности между группами I потоков J и группами J в потоках I?Оба варианта дают одинаковое количество потоков.

2) Предполагая, что мне нужно обработать двумерную матрицу размера, известного только во время выполнения, удобно использовать Dispatch (DimX, DimY, 1) и numthreads (1, 1, 1) так что у меня есть ровно в потоке на матричный элемент, положение которого задается DTid.xy.Поскольку аргументы numthreads () определяются во время компиляции, как я могу получить точное количество потоков, необходимое для обработки матрицы, размеры которой не кратны размеру группы потоков и не известны во время компиляции?

1 Ответ

1 голос
/ 25 сентября 2019

1) Да, есть (или может быть) разница в производительности, в зависимости от фактических чисел и используемого оборудования!

Графические процессоры (обычно) содержат несколько так называемых «волн» потоков.Эти волны работают в стиле SIMD (все потоки в волне всегда выполняют одни и те же операции в одно и то же время).Точное количество потоков на волну зависит от поставщика, но обычно составляет 32 (все известные мне графические процессоры NVidia) или 64 (большинство графических процессоров AMD).

Одна группа потоков может быть распределена на несколько волн.Однако одна волна может выполнять только потоки одной и той же группы.Следовательно, если количество потоков в группе не кратно размеру волны аппаратного обеспечения, в волне есть несколько потоков, которые «простаивают» (на самом деле они выполняют те же действия, что и другие, но им не разрешенозаписывать в память), так что вы «теряете» производительность, которую получили бы с большим числом потоков.

2) Скорее всего, вы выбрали бы число потоков, подходящее для вашего оборудования (64 было бы неплохозначение по умолчанию, так как оно также кратно 32), и используйте разветвление, чтобы пометить потоки как «неактивные», которые находятся за пределами вашей матрицы (вы можете передать размер матрицы / данных в шейдер, используя постоянный буфер).Поскольку эти неактивные потоки вообще ничего не делают, аппаратное обеспечение может просто маскировать их как «только для чтения» (аналогично тому, как они будут обрабатываться, если число потоков в группе меньше размера волны), что довольнодешево.Если все потоки в волне помечены как неактивные, аппаратное обеспечение может даже полностью пропустить работу этой волны, что было бы оптимальным.

Вы также можете использовать заполнение, чтобы убедиться, что ваша матрица / данные всегдакратное количеству потоков в группе, например, с нулями или единичной матрицей или чем-либо еще.Однако то, можно ли это сделать, зависит от приложения, и я бы предположил, что в большинстве случаев ветвление будет таким же быстрым, если не быстрым.

...