【问题标题】:openCL - Creating sub-buffers returns errorcode 13openCL - 创建子缓冲区返回错误代码 13
【发布时间】:2018-08-06 15:42:49
【问题描述】:

您好,我是 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);

【问题讨论】:

    标签: c++ buffer opencl multi-gpu


    【解决方案1】:

    来自documentation

    如果上下文中没有设备与原始值与CL_DEVICE_MEM_BASE_ADDR_ALIGN 值对齐的缓冲区相关联,则CL_MISALIGNED_SUB_BUFFER_OFFSETerrcode_ret 中返回。

    您可能需要将分割区域的偏移量和大小对齐,使其位于所有设备的CL_DEVICE_MEM_BASE_ADDR_ALIGN 属性的最小公倍数 (LCM) 的整数倍上。

    我的意思是这样的:

    假设您使用的设备在变量中

    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++ 标准库功能,因此如果您的工具链中没有该功能,您需要提供 @ 987654322@.)

    【讨论】:

    • 感谢您的回复。但我不明白这是什么意思。是否有示例代码或带有示例的解释?
    • 我不知道示例代码,但我已经编辑了我的答案,让您了解所需的代码类型。
    • 非常感谢。正是我想要的。
    猜你喜欢
    • 1970-01-01
    • 2018-10-01
    • 2023-03-21
    • 1970-01-01
    • 2015-04-01
    • 2020-11-14
    • 2015-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多