#gpu #opencl
#графический процессор #opencl
Вопрос:
Упрощенная проблема У меня есть два потока хоста, каждый со своей собственной очередью команд на одно и то же устройство GPU. Обе очереди вышли из строя, причем порядок выполнения явно управляется с помощью событий ожидания (упрощенный пример в этом не нуждается, но реальное приложение нуждается).
ThreadA
это облегченный конвейер обработки, который выполняется в режиме реального времени по мере получения новых данных. ThreadB
это тяжеловесный конвейер медленной обработки, который использует одни и те же входные данные, но обрабатывает их асинхронно с меньшей скоростью. Я использую двойной буфер, чтобы разделять конвейеры, но позволять ThreadB
работать с одними и теми же входными данными, записанными на устройство с помощью ThreadA
.
ThreadA
цикл:
- Извлечение изображения из сети при наличии данных
- Запишите изображение на устройство
cl_mem BufferA
с помощьюclEnqueueWriteBuffer(CommandQueueA)
- Вызовите обработку изображений
KernelA
с помощьюclEnqueueNDRangeKernel(CommandQueueA)
после завершения записи (ядро выводит результаты вcl_mem OutputA
) - Считывает обработанный результат с
OutputA
помощьюclEnqueueReadBuffer(CommandQueueA)
ThreadB
цикл
- Подождите, пока не пройдет достаточно времени (работает с меньшей скоростью)
- Скопируйте
BufferA
вBufferB
с помощьюclEnqueueCopyBuffer(CommandQueueB)
(двойная замена буфера) - Вызовите более медленную обработку изображений,
KernelB
используяclEnqueueNDRangeKernel(CommandQueueB)
, после завершения копирования (ядро выводит результаты наcl_mem OutputB
) - Считывает обработанный результат с
OutputB
помощьюclEnqueueReadBuffer(CommandQueueB)
Мои вопросы
Между ThreadA
этапом 2 и ThreadB
этапом 2 существует потенциальное состояние гонки. Мне все равно, какая из них выполняется первой, я просто хочу убедиться, что я не копирую BufferA
в BufferB
во время BufferA
записи в.
- Предоставляет ли OpenCL какие-либо неявные гарантии того, что этого не произойдет?
- Если нет, то если я вместо этого на
ThreadB
шаге 2 используюclEnqueueCopyBuffer(CommandQueueA)
так, чтобы операции записи и копирования находились в одной очереди команд, гарантирует ли это, что они не смогут выполняться одновременно, даже если очередь допускает выполнение не по порядку? - Если нет, есть ли лучшее решение, чем добавление события WriteBuffer в
ThreadA
в список ожидания команды CopyBuffer вThreadB
?
Кажется, что любой из них должен работать, но я не могу найти, где в спецификации OpenCL говорится, что это нормально. Пожалуйста, по возможности, укажите спецификацию OpenCL в своих ответах.
Ответ №1:
Предоставляет ли OpenCL какие-либо неявные гарантии того, что этого не произойдет?
Нет, неявной синхронизации не существует, если вы не используете единую очередь команд по порядку.
Если нет, то если я вместо этого на шаге 2 ThreadB использую clEnqueueCopyBuffer (CommandQueueA), чтобы операции записи и копирования находились в одной очереди команд, гарантирует ли это, что они не смогут выполняться одновременно, даже если очередь допускает выполнение не по порядку?
Нет, независимо от типа очереди (по порядку или не по порядку), среда выполнения OpenCL не отслеживает зависимости команд от памяти. Пользователь несет ответственность за указание событий в списке ожидания, если существует какая-либо зависимость между командами.
Следующая цитата может служить доказательством этого:
модель выполнения s3.2.1: контекст и очереди команд
Выполнение не по порядку: команды выдаются по порядку, но не дожидаются завершения перед выполнением следующих команд. Любые ограничения порядка выполняются программистом с помощью явных команд синхронизации.
Это не прямой ответ на ваш вопрос, но я предполагаю, что если были предоставлены какие-либо гарантии, они должны быть упомянуты в этом разделе.
Если нет, есть ли лучшее решение, чем добавление события WriteBuffer в ThreadA в список ожидания команды CopyBuffer в ThreadB?
Если вы можете использовать одну очередь по порядку, это, вероятно, было бы более эффективным, чем событие с перекрестной очередью, по крайней мере, для некоторых реализаций.