GPU запускает потоки в виде групп из 32 потоков, называемых перекосами. Дивергенция может произойти только в основе. Итак, если вы можете упорядочить свои потоки таким образом, чтобы условие if
оценивалось одинаково во всех деформациях, нет никакой дивергенции.
Когда есть расхождение в if
, концептуально GPU просто игнорирует результаты и запросы памяти из потоков, в которых условие if
было ложным.
Итак, скажем, что if
оценивает true
для 10 потоков в определенной деформации. В то время как внутри этого if
потенциальная вычислительная производительность основы уменьшается с 100% до 10/32 * 100 = 31%, поскольку 22 потока, которые были отключены if
, могли выполнять работу, но теперь просто занимают место в деформация.
После выхода из if
отключенные потоки активируются снова, и деформация работает со 100% потенциальной вычислительной производительностью.
if-else
ведет себя точно так же. Когда варп попадает на else
, потоки, которые были включены в if
, отключены, а те, которые были отключены, становятся доступными.
В цикле for
, в котором для каждого потока в warp выполняется определенное количество раз, потоки отключены, так как их число итераций достигает их заданных чисел, но деформация в целом должна продолжаться, пока поток с наивысшей итерацией счет делается.
Рассматривая потенциальную пропускную способность памяти, вещи немного сложнее. Если алгоритм связан с памятью, может быть не так много или какая-либо потерянная производительность из-за разницы в warp, поскольку количество транзакций памяти может быть уменьшено. Если каждый поток в warp читается из совершенно другого места в глобальной памяти (плохая ситуация для графического процессора), время будет сохранено для каждого из отключенных потоков, так как их транзакции памяти не должны выполняться. С другой стороны, если потоки читались из массива, который был оптимизирован для доступа к GPU, несколько потоков будут делиться результатами из одной транзакции. В этом случае значения, предназначенные для отключенных потоков, были прочитаны из памяти, а затем отброшены вместе с вычислениями, которые мог бы сделать отключенный поток.
Итак, теперь у вас, вероятно, есть достаточно обзора, чтобы иметь возможность делать довольно здравые рассуждения о том, сколько разницы в деформации повлияет на вашу производительность. Худший случай - когда активен только один поток в warp. Затем вы получаете 1/32 = 3,125% от потенциала для производительности, связанной с вычислением. Лучший случай - 31/32 = 96,875%. Для if
, который является полностью случайным, вы получаете 50%. И, как уже упоминалось, производительность памяти зависит от изменения количества требуемых транзакций памяти.
Будут ли разные потоки иметь различное количество итераций цикла (номер 100/1000/10000, который вы цитируете)? –
@Brendan Wood: Нет, все они будут иметь одинаковое значение, но как только поток попадет в блок if, этот поток вырвется из цикла независимо от значения i. О, и тогда эта нить начнется с самого начала. Возможно, мне следует изменить образец кода, чтобы это отразить. – Konstantinos