2012-01-26 4 views
2

Учитывая float[n] inputdata передать ядру OpenCL, может кто-нибудь просветить меня о различии между следующими тремя способами, чтобы передать это ядро:JOCL: зачем использовать буферы?

A)

cl_mem input = clCreateBuffer(context, CL_MEM_USE_HOST_PTR Sizeof.cl_float * n, 
     inputdata, NULL); 
clSetKernelArg(kernel, i, Sizeof.cl_mem, Pointer.to(input)); 

B)

clSetKernelArg(kernel, i, Sizeof.cl_float * n, Pointer.to(inputdata)); 

С)

cl_mem input = clCreateBuffer(context, CL_MEM_options_here, Sizeof.cl_float * n, 
     NULL, NULL); 
clEnqueueWriteBuffer(command_queue, input, CL_TRUE, 0, Sizeof.cl_float * n, 
     inputdata, 0, NULL, NULL); 
clSetKernelArg(kernel, i, Sizeof.cl_mem, Pointer.to(input)); 

?

Я правильно понял, что разница между A) и C) заключается в том, что C) копирует весь массив один раз в начале и затем работает с ним с GPU, тогда как A) должен загружать свои данные в режиме реального времени, летать? Итак, A) хорошо, если требуется только небольшая часть массива, а C) - это способ пойти, если вы все равно используете весь массив?

А как насчет B)? Это больше похоже на A), больше похоже на C) или еще что-то другое?

ответ

1

Да, вы не можете передавать огромное количество параметров. Верхний предел размера всех параметров (обычно в диапазоне 50 KiB - вы можете запросить его с помощью clGetDeviceInfo и CL_DEVICE_MAX_PARAMETER_SIZE). С помощью методов a и c вы можете передавать гораздо большие буферы (сотни мегабайт). A не полезно для OpenCL 1.1 и ниже, поскольку буфер будет по-прежнему скопирован обычно, но с OpenCL 1.2 вы можете избежать одной копии, если ваш хост и устройство же (т.е. вы используете CPU OpenCL выполнения, например.)

+0

Таким образом, ограничение по размеру - это * только * разница? Например. до тех пор, пока B) работает, на самом деле нет причин использовать A) или C)? И будет ли он быстрее, чем A) и C), или медленнее (например, когда содержимое массива изменяется с помощью хоста) или они действительно эквивалентны? – user1111929

+0

Семантика и размер. Если это буфер, вы должны использовать буфер, так как максимальный размер параметра может быть не меньше 256 байтов (!). Осторожнее с плакатом mfa, он ошибается, так как вы не можете легко передать данные в __local; вы можете установить размер __local-буфера во время вызова ядра (вам все равно нужно скопировать данные в __local.) Я бы использовал a, если вам нужно всего лишь получить данные на GPU. – Anteru

0

Что каждый делает метод:

A) Этот метод использует буфер хоста для хранения данных. Если вы не хотите копировать данные на устройство, но хотите использовать его на месте. Я считаю, что это возможно только на устройствах ЦП, но я не совсем уверен.

B) Пропускает __global * тип вашего ядра. Используйте это для ограниченного объема данных. Помните, что для версии __local/NULL этого производительность может быть значительно (и отрицательно) вызвана большим количеством рабочих элементов/групп. Размер ограничен CL_DEVICE_MAX_PARAMETER_SIZE. Передача NULL приведет к типу __local *, а предел - CL_DEVICE_LOCAL_MEM_SIZE.

C) Используйте это, когда у вас есть большой (то есть больший, чем предел метода B) объем данных, необходимых вашему ядру. Это копирует данные из буфера вашего хоста в буфер устройства. Если ваши данные готовы к использованию, вы можете использовать флаг mem CL_MEM_COPY_HOST_PTR, чтобы скопировать его при создании буфера cl_mem и пропустить вызов clEnqueueWriteBuffer.

+0

Не могли бы вы предоставить мне ссылку на утверждение о том, что B) автоматически передает переменную как __local? Это звучит довольно странно, поскольку, похоже, это не так для переменных без массива. – user1111929

+0

Это неправильно: см. Документацию по адресу http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clSetKernelArg.html.Если вы передаете null в качестве указателя и только передаете размер, тогда вы указываете размер локального буфера (указатель ДОЛЖЕН быть нулевым, поэтому вы не можете распределять и копировать данные в локальный буфер во время вызова ядра.) – Anteru

+1

Моя ошибка, Он должен быть NULL для __local. В этом случае вы связаны CL_DEVICE_LOCAL_MEM_SIZE. В противном случае это __global, а предел - CL_DEVICE_MAX_PARAMETER_SIZE. – mfa

Смежные вопросы