2016-10-26 4 views
1

Я относительно новичок в OpenCL. Я использую оболочку OpenCL 1.2 C++. Скажем, у меня есть следующая проблема: У меня есть три целочисленные значения а, Ь и с всем объявленный на хостеПередача переменных между ядрами в OpenCL 1.2/Связь между ядрами

int a = 1; 
int b = 2; 
int c = 3; 
int help; 
int d; 

с d быть моим результат и поможет быть переменной помощь.

Я хочу рассчитать d = (a + b) * c. Для этого у меня теперь есть два ядра, называемые «add» и «multiply».

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

bufferA = new cl::Buffer(*context, CL_MEM_READ_ONLY, buffer_length); 
cl::Buffer bufferB = new cl::Buffer(*context, CL_MEM_READ_ONLY, buffer_length); 
bufferC = new cl::Buffer(*context, CL_MEM_READ_ONLY, buffer_length); 
bufferHelp = new cl::Buffer(*context, CL_MEM_READ_WRITE, buffer_length); 
bufferD = new cl::Buffer(*context, CL_MEM_WRITE_ONLY, buffer_length); 

Затем я установил мои аргументы ядра для добавление ядра

add->setArg(0, *bufferA); 
add->setArg(1, *bufferB); 
add->setArg(2, *bufferHelp); 

и для multiplicatoin ядра

multiply->setArg(0, *bufferC); 
multiply->setArg(1, *bufferHelp); 
multiply->setArg(2, *bufferD); 

Тогда я епдиеие мои данные для добавления

queueAdd->enqueueWriteBuffer(*bufferA, CL_TRUE, 0, datasize, &a); 
queueAdd->enqueueWriteBuffer(*bufferB, CL_TRUE, 0, datasize, &b); 
queueAdd->enqueueNDRangeKernel(*add, cl::NullRange, global[0], local[0]); 
queueAdd->enqueueReadBuffer(*bufferHelp, CL_TRUE, 0, datasize, &help); 

и для умножения

queueMult->enqueueWriteBuffer(*bufferC, CL_TRUE, 0, datasize, &c); 
queueMult->enqueueWriteBuffer(*bufferHelp, CL_TRUE, 0, datasize, &help); 
queueMult->enqueueNDRangeKernel(*multiply, cl::NullRange, global[0], local[0]); 
queueMult->enqueueReadBuffer(*bufferD, CL_TRUE, 0, datasize, &d); 

Это работает в прекрасном пути. Тем не менее, я не хочу копировать значение справки обратно на хост, а затем снова на устройство. Чтобы достичь этого, я подумал о 3 возможностях:

  1. глобальная переменная для помощи со стороны устройства. При этом оба ядра могли получить доступ к значению справки в любое время.
  2. Ядро, добавляющее ядро ​​вызова, умножается на время выполнения. Затем мы вставляем значение для c в ядро ​​добавления и передаем как справку, так и c в многократное ядро, как только добавление завершится.
  3. Просто передайте значение справки в ядро ​​умножения. Я ищу здесь нечто вроде объекта pipe, доступного для OpenCL 2.0. Кто-нибудь знает что-то подобное для OpenCL 1.2.?

Я был бы очень благодарен, если бы кто-нибудь мог предложить самый гладкий способ решить мою проблему!

Заранее благодарен!

ответ

2

Нет необходимости читать и писать bufferHelp. Просто оставьте это в памяти устройства. Номер 1) из вашего предлагаемого решения так же, как cl::Buffers, globals в памяти устройства.

Это эквивалентно код и будет производить такие же результаты:

queueAdd->enqueueWriteBuffer(*bufferA, CL_FALSE, 0, datasize, &a); 
queueAdd->enqueueWriteBuffer(*bufferB, CL_FALSE, 0, datasize, &b); 
queueAdd->enqueueNDRangeKernel(*add, cl::NullRange, global[0], local[0]); 
//queueAdd->enqueueReadBuffer(*bufferHelp, CL_FALSE, 0, datasize, &help); 

queueMult->enqueueWriteBuffer(*bufferC, CL_FALSE, 0, datasize, &c); 
//queueMult->enqueueWriteBuffer(*bufferHelp, CL_FALSE, 0, datasize, &help); 
queueMult->enqueueNDRangeKernel(*multiply, cl::NullRange, global[0], local[0]); 
queueMult->enqueueReadBuffer(*bufferD, CL_TRUE, 0, datasize, &d); 

ПРИМЕЧАНИЕ: Я также изменил звонки блокировки записи, это обеспечит гораздо более высокую скорость, так как копия буфера C и исполнения ядра «добавить» можно распараллелить.

+0

Вау, я не могу поверить, что это так просто, спасибо большое !!! Просто для других читателей: я добавил queueAdd-> finish(); в конце первого блока в приведенном выше ответе, чтобы убедиться, что первое ядро ​​закончено. – YeahScience