OpenCL: параллельная запись из хоста в буфер устройства? - PullRequest
0 голосов
/ 03 декабря 2018

У меня довольно большой буфер cl_mem (100 миллионов операций с плавающей запятой).Я пытаюсь уменьшить количество времени, которое требуется, чтобы заполнить его данными с хоста (мне приходится много раз передавать данные с хоста на устройство, и в настоящее время я каждый раз заново инициализирую буфер).

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

Возможен ли такой подход?Я посмотрел в clEnqueueWriteBuffer, и хотя он позволяет обновлять подмножество буфера, кажется, что несколько вызовов к нему все равно будут последовательно выполняться очередью команд.Мне нужно несколько командных очередей?Возможен ли такой подход?

1 Ответ

0 голосов
/ 04 декабря 2018

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

Ваши измерения предполагают, что вы не ограниченыинтерфейс между вашим процессором и устройством?Поскольку, если вам нужно каждый раз копировать N МБ, ваше устройство подключается к памяти ЦП / системы через интерфейс B МБ / с, а время копирования не превышает N / B секунд, никакая многопоточность не поможетyou.

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

Если это слишком громоздко для ваших целей, может быть полезно использовать clEnqueueMapBuffer для сопоставления буфера с адресным пространством приложения хоста,Это позволяет любому количеству потоков одновременно обращаться к произвольным областям.Имейте в виду, однако, что это не серебряная пуля, и если ваша реализация OpenCL явно не определяет, как это реализовано на практике, может случиться так, что вы действительно ухудшите ситуацию, потому что это может привести к копированию more чем раньше.

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

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

...