JOCL: зачем использовать буферы?
Учитывая, что float[n] inputdata
передается ядру OpenCL, может ли кто-нибудь просветить меня относительно разницы между следующими тремя способами передачи этого в ядро:
А)
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));
C)
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) должен загружать свои данные на лету? Поэтому а) хорошо, если требуется только небольшая часть массива, и в) есть ли способ пойти, если вы все равно используете весь массив?
А как насчет Б)? Это больше похоже на А), больше похоже на С) или все-таки что-то другое?
2 ответа:
Да, вы не можете передать огромное количество параметров. Существует верхний предел размера всех параметров (обычно в диапазоне 50 Кб-вы можете запросить его с помощью
clGetDeviceInfo
иCL_DEVICE_MAX_PARAMETER_SIZE
). С помощью методов a и c можно передавать буферы гораздо большего размера (сотни мегабайт.) a не полезен для OpenCL 1.1 и ниже, так как буфер будет по-прежнему копироваться обычно, но с OpenCL 1.2 вы можете избежать одной копии, если ваш хост и устройство одинаковы (например, вы используете CPU OpenCL runtime).)
Что делает каждый метод:
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 вызов.