Гарантирует ли OpenCL целостность буферной памяти при наличии нескольких очередей команд?

#gpu #opencl

#графический процессор #opencl

Вопрос:

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

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

ThreadA цикл:

  1. Извлечение изображения из сети при наличии данных
  2. Запишите изображение на устройство cl_mem BufferA с помощью clEnqueueWriteBuffer(CommandQueueA)
  3. Вызовите обработку изображений KernelA с помощью clEnqueueNDRangeKernel(CommandQueueA) после завершения записи (ядро выводит результаты в cl_mem OutputA )
  4. Считывает обработанный результат с OutputA помощью clEnqueueReadBuffer(CommandQueueA)

ThreadB цикл

  1. Подождите, пока не пройдет достаточно времени (работает с меньшей скоростью)
  2. Скопируйте BufferA в BufferB с помощью clEnqueueCopyBuffer(CommandQueueB) (двойная замена буфера)
  3. Вызовите более медленную обработку изображений, KernelB используя clEnqueueNDRangeKernel(CommandQueueB) , после завершения копирования (ядро выводит результаты на cl_mem OutputB )
  4. Считывает обработанный результат с OutputB помощью clEnqueueReadBuffer(CommandQueueB)

Мои вопросы

Между ThreadA этапом 2 и ThreadB этапом 2 существует потенциальное состояние гонки. Мне все равно, какая из них выполняется первой, я просто хочу убедиться, что я не копирую BufferA в BufferB во время BufferA записи в.

  1. Предоставляет ли OpenCL какие-либо неявные гарантии того, что этого не произойдет?
  2. Если нет, то если я вместо этого на ThreadB шаге 2 использую clEnqueueCopyBuffer(CommandQueueA) так, чтобы операции записи и копирования находились в одной очереди команд, гарантирует ли это, что они не смогут выполняться одновременно, даже если очередь допускает выполнение не по порядку?
  3. Если нет, есть ли лучшее решение, чем добавление события WriteBuffer в ThreadA в список ожидания команды CopyBuffer в ThreadB ?

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

Ответ №1:

Предоставляет ли OpenCL какие-либо неявные гарантии того, что этого не произойдет?

Нет, неявной синхронизации не существует, если вы не используете единую очередь команд по порядку.

Если нет, то если я вместо этого на шаге 2 ThreadB использую clEnqueueCopyBuffer (CommandQueueA), чтобы операции записи и копирования находились в одной очереди команд, гарантирует ли это, что они не смогут выполняться одновременно, даже если очередь допускает выполнение не по порядку?

Нет, независимо от типа очереди (по порядку или не по порядку), среда выполнения OpenCL не отслеживает зависимости команд от памяти. Пользователь несет ответственность за указание событий в списке ожидания, если существует какая-либо зависимость между командами.

Следующая цитата может служить доказательством этого:

модель выполнения s3.2.1: контекст и очереди команд

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

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

Если нет, есть ли лучшее решение, чем добавление события WriteBuffer в ThreadA в список ожидания команды CopyBuffer в ThreadB?

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