Функция Python, которая получает неизвестное количество аргументов

С этим ответом я только пытаюсь предоставить более подробные сведения о подходе Давиде Спатаро.

Как вы упомянули, сжатие потока состоит в удалении нежелательных элементов в коллекции в зависимости от предиката. Например, рассматривая массив целых чисел и предикат p(x)=x>5, массив A={6,3,2,11,4,5,3,7,5,77,94,0} сжимается до B={6,11,7,77,94}.

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

Подход в [1,2] является альтернативой упомянутому [Th5ust] выше и состоит из трех этапов:

  1. Шаг # 1. Пусть P - количество запущенных потоков и N, с N>P - размер вектора, подлежащего уплотнению. Входной вектор делится на подвектор размером S, равным размеру блока. Используется встроенный блок __syncthreads_count(pred), который подсчитывает количество потоков в блоке, удовлетворяющем предикату pred. В результате первого шага каждый элемент массива d_BlockCounts, который имеет размер N/P, содержит число элементов, удовлетворяющих предикату pred в соответствующем блоке.
  2. Шаг # 2. Эксклюзивная операция сканирования выполняется на массиве d_BlockCounts. В результате второго шага каждый поток знает, сколько элементов в предыдущих блоках записывает элемент. Соответственно, он знает позицию, где следует писать соответствующий элемент, но для смещения, связанного с его собственным блоком.
  3. Шаг №3. Каждый поток вычисляет упомянутое смещение с использованием встроенных функций warp и в конечном итоге записывает в выходной массив. Следует отметить, что выполнение шага 3 связано с планированием warp. Как следствие, порядок элементов в выходном массиве не обязательно отражает порядок элементов во входном массиве.

Из трех шагов выше второй выполняется CUDA Thrust's exclusive_scan примитивный и вычислительно значительно менее требовательный, чем два других.

Для массива элементов 2097152 упомянутый подход выполнен в 0.38ms на карте NVIDIA GTX 960, в отличие от 1.0ms CUDA Thrust's copy_if. Упомянутый подход работает быстрее по двум причинам: 1) он специально предназначен для карточек, поддерживающих внутренние элементы основы; 2) Подход не гарантирует упорядочение вывода.

Следует заметить, что мы протестировали подход и против кода, доступного в inkc.sourceforge.net . Хотя последний код устроен одним вызовом ядра (он не использует примитив CUDA Thrust), он не имеет лучшей производительности по сравнению с версией с тремя ядрами.

Полный код доступен здесь и немного оптимизирован по сравнению с обычной процедурой Дейвида Спатаро.

[1] M.Biller, O. Olsson, U. Assarsson, “Efficient stream compaction on wide SIMD many-core architectures,” Proc. of the Conf. on High Performance Graphics, New Orleans, LA, Aug. 01 - 03, 2009, pp. 159-166.
[2] D.M. Hughes, I.S. Lim, M.W. Jones, A. Knoll, B. Spencer, “InK-Compact: in-kernel stream compaction and its application to multi-kernel data visualization on General-Purpose GPUs,” Computer Graphics Forum, vol. 32, n. 6, pp. 178-188, 2013.

2
задан hil 25 March 2019 в 16:27
поделиться