OpenCL перекрывает связь и вычисления

В OpenCL NVIDIA SDK есть пример, oclCopyComputeOverlap, который использует 2 очереди для поочередной передачи буферов/выполнения ядер. В этом примере используется отображаемая память.

**//pinned memory** 
cmPinnedSrcA = clCreateBuffer(cxGPUContext, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, szBuffBytes, NULL, &ciErrNum);
**//host pointer for pinned memory**
fSourceA = (cl_float*)clEnqueueMapBuffer(cqCommandQueue[0], cmPinnedSrcA, CL_TRUE,    CL_MAP_WRITE, 0, szBuffBytes, 0, NULL, NULL, &ciErrNum);
...
**//normal device buffer**
cmDevSrcA = clCreateBuffer(cxGPUContext, CL_MEM_READ_ONLY, szBuffBytes, NULL, &ciErrNum);
**//write half the data from host pointer to device buffer**
ciErrNum = clEnqueueWriteBuffer(cqCommandQueue[0], cmDevSrcA, CL_FALSE, 0, szHalfBuffer, (void*)&fSourceA[0], 0, NULL, NULL);

У меня 2 вопроса: 1) Нужно ли использовать закрепленную память, чтобы произошло перекрытие? Не мог ли fSourceA быть просто указателем хоста,

fSourceA = (cl_float *)malloc(szBuffBytes);
...
//write random data in fSourceA

2) cmPinnedSrcA в ядре не используется, вместо него используется cmDevSrcA. Разве место, занимаемое буферами на устройстве, не растет? (пространство, необходимое для cmPinnedSrcA, добавляется к пространству, необходимому для cmDevSrcA)

Спасибо


person user2694398    schedule 18.08.2013    source источник


Ответы (1)


Если я правильно понял ваш вопрос:

1) Да, вы можете использовать любую память (закрепленную, указатель хоста и т. д.), и перекрытие все равно будет происходить. Насколько вы используете две очереди и аппаратное обеспечение/драйверы поддерживают это.

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

2) Я думаю, что вы используете в 2 раза больше памяти, если используете закрепленную память, одну для закрепленной, а другую для временной копии. Но я не уверен на 100%, может быть, это всего лишь указатель.

person DarkZeros    schedule 18.08.2013
comment
Большое спасибо за ответ. Но я так и не понял следующее: 1)Почему он там использует закрепленную память, ведь схема такая: создаем 3 закрепленных буфера, pinnedA,pinnedB,pinnedResult; создавать закрепленные указатели, flA, flB, flResult; создать 3 обычных буфера, A, B, Result; поставить в очередь запись из указателя хоста flA в A (половина размера), записать из flB в B (половина размера) в очереди 1; поставить в очередь ядро ​​K1 в очереди 1, поставить в очередь запись из flA в A (другая половина), записать из flB в B (другая половина) в очереди 2; - person user2694398; 19.08.2013
comment
поставить в очередь чтение из результата (первая половина) в flResult в очереди 1, поставить в очередь ядро ​​K2 в очереди 2; enqueue read Result (другая половина) в Queue 2. Ядра используют только A, B, Result в качестве буферов. 2) Я имел в виду размер закрепленных буферов (pinnedA, pinnedB, pinnedResult), который добавляется к размеру других (A, B, Result). В любом случае, еще раз спасибо за столь быстрый ответ - person user2694398; 19.08.2013
comment
Я действительно не знаю в деталях, как работает закрепленный. Но такой способ использования типичен для закрепленной памяти. - person DarkZeros; 19.08.2013