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 2

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 вызов.