__activemask () против __ballot_sync () - PullRequest
0 голосов
/ 05 января 2019

После прочтения этой записи в блоге разработчиков CUDA, я изо всех сил пытаюсь понять, когда безопасно \ правильно использовать __activemask() вместо __ballot_sync().

В разделе Active Mask Query , авторы написали:

Это неверно, так как это приведет к частичной сумме вместо общая сумма.

и после, в разделе Оппортунистическое программирование на уровне деформации они используют функцию __activemask(), потому что:

Это может быть сложно, если вы хотите использовать программирование на уровне деформации внутри функция библиотеки, но вы не можете изменить интерфейс функции.

1 Ответ

0 голосов
/ 05 января 2019

В CUDA нет __active_mask(). Это опечатка (в статье блога). Это должно быть __activemask().

__activemask() - это только запрос . Он задает вопрос "какие потоки в варпе в настоящее время выполняют эту инструкцию в этом цикле?" что равносильно тому, чтобы спросить «какие потоки в варпе в данный момент сходятся?»

Не влияет на конвергенцию. Это не приведет к схождению потоков. У него нет режима синхронизации варпа.

__ballot_sync(), с другой стороны, имеет сходящееся поведение (согласно предоставленному mask).

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

Дивергенция, на которую мы ссылаемся здесь, является случайной дивергенцией из-за предыдущего условного исполнения. Принудительное расхождение из-за явного кодирования идентично до или после Вольта.

Давайте рассмотрим пример:

if (threadIdx.x < 1){
   statement_A();}
statement_B();

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

А как насчет statement_B()? Модель выполнения CUDA не делает никаких конкретных заявлений о том, будет ли деформация в дивергентном состоянии или нет при выполнении statement_B(). В среде исполнения, предшествовавшей Volta, программисты, как правило, ожидали, что в закрывающей фигурной скобке предыдущего оператора if есть какая-то перекос конверсии (хотя CUDA не гарантирует этого). Поэтому общее ожидание состоит в том, что statement_B() будет выполнено в неотклоненном состоянии.

Однако в модели исполнения Volta не только нет никаких гарантий, предоставляемых CUDA, но на практике мы можем наблюдать деформацию в отклоненном состоянии в statement_B(). Дивергенция в statement_B() не требуется для правильности кода (тогда как это требуется в statement_A()), а также конвергенция в statement_B() не требуется моделью исполнения CUDA. Если в statement_B() есть расхождение, которое может возникнуть в модели исполнения Volta, я имею в виду это как случайное расхождение. Это расхождение возникает не из-за какого-то требования кода, а из-за какого-то предыдущего поведения условного выполнения.

Если у нас нет расхождения в statement_B(), то эти два выражения (если они были в statement_B()) должны возвращать один и тот же результат:

int mask = __activemask();

и

int mask = __ballot_sync(0xFFFFFFFF, 1);

Таким образом, в случае перед напряжением, когда мы обычно не ожидаем расхождения на statement_B(), на практике эти два выражения возвращают одно и то же значение.

В модели исполнения Volta у нас может быть случайная дивергенция в statement_B(). Поэтому эти два выражения могут не возвращать один и тот же результат. Почему?

Инструкция __ballot_sync(), как и все другие встроенные функции уровня CUDA 9+, имеющие параметр маски, имеет синхронизирующий эффект . Если у нас есть принудительное расхождение с кодом, если не удается выполнить синхронизирующий «запрос», указанный аргументом маски (как в случае выше, когда мы запрашиваем полную конвергенцию), это будет представлять недопустимый код.

Однако, если у нас случайная дивергенция (только для этого примера), семантика __ballot_sync() должна сначала реконвертировать деформацию по крайней мере в той степени, в которой аргумент маски запрашивает , затем выполните запрошенную операцию голосования.

Операция __activemask() не имеет такого поведения реконвергенции. Он просто сообщает о потоках, которые в настоящее время сходятся. Если некоторые потоки расходятся по по любой причине , они не будут указаны в возвращаемом значении.

Если затем вы создали код, выполняющий некоторую операцию на уровне деформации (например, уменьшение суммы на уровне деформации, как предлагается в статье блога), и выбрали потоки для участия на основе __activemask() против __ballot_sync(0xFFFFFFFF, 1), вы могли бы возможно получить другой результат, при наличии случайной дивергенции. Реализация __activemask(), при наличии случайной дивергенции, будет вычислять результат, который не включает все потоки (то есть она будет вычислять «частичную» сумму). С другой стороны, реализация __ballot_sync(0xFFFFFFFF, 1), поскольку она сначала устранила бы случайное расхождение, вынудила бы участвовать все потоки (вычисляя «общую» сумму).

Пример и описание, аналогичные приведенным здесь, приведены в листинге 10 в статье блога.

Пример правильного использования __activemask приведен в статье в блоге "Оппортунистическое программирование на уровне деформации", здесь:

int mask = __match_all_sync(__activemask(), ptr, &pred);

это утверждение говорит "скажите мне, какие потоки сходятся" (т.е. запрос __activemask()), а затем "используйте (как минимум) эти потоки для выполнения операции __match_all. Это совершенно законно и будет использовать все, что угодно в этот момент потоки сходятся. По мере продолжения этого примера листинга 9 mask, вычисленный на предыдущем шаге, используется в единственном другом примитиве, совместимом с варпом:

res = __shfl_sync(mask, res, leader); 

(что происходит сразу после фрагмента условного кода). Это определяет, какие потоки доступны, а затем вынуждает использовать эти потоки независимо от того, какая случайная дивергенция могла существовать, для получения предсказуемого результата.

...