Хотя для эффективной работы требуется больше шагов, это компенсируется тем, что число активных потоков уменьшается быстрее, а общее количество активных потоков за все итерации значительно меньше. Если деформация не имеет активных потоков во время итерации, эта деформация просто перейдет к следующему барьеру и будет приостановлена, позволяя другим деформациям работать. Таким образом, меньшее количество активных деформаций часто окупается во время выполнения. (Это подразумевает, что код GPU должен быть спроектирован таким образом, чтобы активные потоки были упакованы в минимально возможное количество деформаций - вы не хотите, чтобы они были разбросаны редко, поскольку даже один активный поток вызовет весь деформацию оставаться активным.)
Рассмотрим количество активных потоков в наивном алгоритме. Посмотрев на рисунок 2 в статье, вы можете увидеть, что все потоки активны, за исключением первых 2 k на k- й итерации. Таким образом, для N потоков количество активных потоков равно N - 2 k . Например, при N = 1024 число активных потоков за итерацию равно:
1023, 1022, 1020, 1016, 1008, 992, 960, 896, 768, 512
Если я преобразую это в число активных деформаций (путем деления на 32 и округления вверх), я получу:
32, 32, 32, 32, 32, 31, 30, 28, 24, 16
на сумму 289. С другой стороны, эффективный алгоритм запускается с вдвое меньшим количеством потоков, затем он вдвое сокращает количество активных на каждой итерации до тех пор, пока не опустится до 1, а затем начнет удваиваться, пока не вернется к снова половина размера массива:
512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512
Преобразование этого в активные деформации:
16, 8, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 8, 16
Сумма составляет 71, что всего на четверть больше. Таким образом, вы можете видеть, что в течение всей операции число активных деформаций намного меньше с эффективным алгоритмом работы. (Фактически, для длительного прогона в середине есть только несколько активных деформаций, что означает, что большая часть микросхемы не занята. Если выполняются дополнительные вычислительные задачи, например, из других потоков CUDA, они могут расширяться, чтобы заполнить это незанятое пространство.)