Что делает mem_fence () в OpenCL, в отличие от барьера ()? - PullRequest
11 голосов
/ 06 октября 2011

В отличие от barrier() (что, я думаю, я понимаю), mem_fence() не влияет на все элементы в рабочей группе.Спецификация OpenCL говорит (раздел 6.11.10), для mem_fence():

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

(так чтоприменяется к одному рабочему элементу.

Но в то же время в разделе 3.3.1 говорится, что:

В рамкахпамять элемента имеет согласованную загрузку / хранение.

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

Итак, что за вещь mem_fence() полезна для?Он не работает между элементами, но не требуется для элемента ...

Обратите внимание, что я не использовал атомарные операции (раздел 9.5 и т. Д.).Идея, что mem_fence() используется вместе с ними?Если это так, я хотел бы видеть пример.

Спасибо.

Спецификация, для справки.

Обновление : Я вижу, как это полезно, когда используется с barrier() (неявно, поскольку барьер вызывает mem_fence()) - но, безусловно, должно быть больше, поскольку оно существует отдельно?

Ответы [ 3 ]

6 голосов
/ 06 октября 2011

Чтобы попытаться выразить это более четко (надеюсь),

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

Это происходит из: http://developer.download.nvidia.com/presentations/2009/SIGGRAPH/asia/3_OpenCL_Programming.pdf

Операции с памятью могут быть переупорядочены в соответствии с устройством, на котором они работают.Спецификация утверждает (в основном), что любое переупорядочение операций с памятью должно гарантировать, что память находится в согласованном состоянии в пределах одного рабочего элемента.Однако что, если вы (например) выполняете операцию сохранения, и значение решает жить в кеше, относящемся к конкретному рабочему элементу, пока не наступит лучшее время для записи в локальную / глобальную память?Если вы попытаетесь загрузить из этой памяти, рабочий элемент, который записал значение, поместит его в кэш, так что никаких проблемНо другие рабочие элементы в рабочей группе этого не делают, поэтому они могут прочитать неправильное значение.Установка ограничителя памяти гарантирует, что во время вызова ограничителя памяти локальная / глобальная память (согласно параметрам) будет сделана согласованной (все кэши будут очищены, и любое переупорядочение будет учитывать то, что вы ожидаете, что другие потоки могутмне нужно получить доступ к этим данным после этого момента).

Я признаю, что это все еще сбивает с толку, и я не буду клясться, что мое понимание на 100% верно, но я думаю, что это по крайней мере общая идея.

Follow Up:

Я нашел эту ссылку, которая говорит о заборах памяти CUDA, но та же общая идея применима к OpenCL:

http://developer.download.nvidia.com/compute/cuda/2_3/toolkit/docs/NVIDIA_CUDA_Programming_Guide_2.3.pdf

Извлечение раздела B.5 Функции забора памяти .

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

Итак, в каждой рабочей группе в основном делается 2 вещи: частичная сумма, которая обновляет глобальную переменную., затем атомарное приращение глобальной переменной счетчика.

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

Теперь проблема (как они это объясняют) состоит в том, что из-за переупорядочения памяти и / или кэширования счетчик может увеличиваться, а последняя работа -Группа может начать выполнять свою работу до того, как глобальная переменная с частичной суммой получит свое последнее значение, записанное в глобальную память.

Ограничение памяти обеспечит согласованность значения этой переменной с частичной суммой для всех потоков перед перемещением.мимо забора.

Надеюсь, в этом есть какой-то смысл.Это сбивает с толку.

0 голосов
/ 17 мая 2016

Вот как я это понимаю (я все еще пытаюсь это проверить)

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

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

Другими словами, barrier - это расширенный набор mem_fence.barrier может оказаться дороже с точки зрения производительности, чем mem_fence.

0 голосов
/ 22 февраля 2013

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

...