openCL — Создание подбуферов возвращает код ошибки 13

Привет, я новичок в OpenCL и использую оболочку C ++. Попытка запустить одно и то же ядро ​​на двух устройствах одновременно. Буфер создается, и попытка состоит в том, чтобы разделить его на части с использованием подбуферов и передать эти фрагменты ядру и отправить их дважды — один раз в Командную очередь 1, а затем в Командную очередь 2 с различными фрагментами основного буфера.

При запуске выдает ошибку -13. Все остальные подбуферы были созданы, кроме этого.

Любое руководство будет высоко ценится.

Использование OpenCL 1.1

//Creating main buffer
cl::Buffer zeropad_buf(openclObjects.context,CL_MEM_READ_ONLY| CL_MEM_COPY_HOST_PTR,(size+2)*(size+2)*cshape[level][1]*sizeof(float),zeropad);
cl::Buffer output_buf(openclObjects.context,CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR  ,cshape[level][0]*size*size*sizeof(float),output_f);

//Creating sub_buffers for zeropad_buf
size_t zeropad_buf_size = (size+2)*(size+2)*cshape[level][1]*sizeof(float);
size_t output_buf_size = cshape[level][0]*size*size*sizeof(float);

cl_buffer_region zero_rgn_4core = {0, zeropad_buf_size/2};
**cl_buffer_region zero_rgn_2core = {zeropad_buf_size/2, zeropad_buf_size/2};** //Throws error -13

cl_buffer_region output_rgn_4core = {0, output_buf_size/2};
cl_buffer_region output_rgn_2core = {output_buf_size/2, output_buf_size/2};cl::Buffer zeropad_buf_4Core = zeropad_buf.createSubBuffer(CL_MEM_READ_ONLY,CL_BUFFER_CREATE_TYPE_REGION, &zero_rgn_4core);
**cl::Buffer zeropad_buf_2Core = zeropad_buf.createSubBuffer(CL_MEM_READ_ONLY,CL_BUFFER_CREATE_TYPE_REGION, &zero_rgn_2core);**
std::cout<<"zero_pad sub-buffer created"<<std::endl;

cl::Buffer output_buf_4Core = output_buf.createSubBuffer(CL_MEM_READ_WRITE,CL_BUFFER_CREATE_TYPE_REGION, &output_rgn_4core);
cl::Buffer output_buf_2Core = output_buf.createSubBuffer(CL_MEM_READ_WRITE,CL_BUFFER_CREATE_TYPE_REGION, &output_rgn_2core);

1

Решение

От документация:

CL_MISALIGNED_SUB_BUFFER_OFFSET возвращается в errcode_ret если в контексте нет устройств, связанных с буфером, для которого значение источника выровнено по CL_DEVICE_MEM_BASE_ADDR_ALIGN значение.

Похоже, что вам может потребоваться выровнять смещения и размеры разделенной области, чтобы они лежали на целых кратных наименьшего общего кратного (LCM) CL_DEVICE_MEM_BASE_ADDR_ALIGN свойства всех ваших устройств.

Под этим я подразумеваю что-то вроде следующего:

Предполагая, что используемые вами устройства находятся в переменной

std::vector<cl::Device> devices;

Запрос CL_DEVICE_MEM_BASE_ADDR_ALIGN свойство для каждого устройства:

cl_uint total_alignment_requirement = 1;
for (cl::Device& dev : devices)
{
cl_uint device_mem_base_align = 0;
if (CL_SUCCESS == dev.getInfo(CL_DEVICE_MEM_BASE_ADDR_ALIGN, &device_mem_base_align))
total_alignment_requirement = std::lcm(total_alignment_requirement, device_mem_base_align);
}

Затем, когда дело доходит до распределения zeropadубедитесь, что память выровнена total_alignment_requirementНапример, если вы в настоящее время выделяете его malloc()использовать posix_memalign() вместо. (Даже лучше, не создавайте буфер, используя CL_MEM_USE_HOST_PTR и пусть OpenCL выделит память, если вы можете.)

Наконец, ваши регионы тоже должны быть выровнены:

size_t zeropad_split_pos = zeropad_buf_size / 2;
zeropad_split_pos -= zeropad_split_pos % total_alignment_requirement;
cl_buffer_region zero_rgn_4core = {0, zeropad_split_pos};
cl_buffer_region zero_rgn_2core = {zeropad_split_pos, zeropad_buf_size - zeropad_split_pos};

Это гарантирует, что первый регион начинается и заканчивается на адресе, кратном total_alignment_requirement, а вторая область тоже начинается по выровненному адресу.

(Я не проверял этот код, но он должен быть близок к правильному. Обратите внимание, что std::lcm это очень новая функция стандартной библиотеки C ++, поэтому, если она не доступна в вашем наборе инструментов, вам потребуется ваша собственная функция lcm.)

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]