我目前正在尝试熟悉使用 OpenCL 的异构编程,并且很难理解如何集成来自不同平台的设备。
在下面的示例中,我尝试在不同的设备/平台上执行依赖内核。但是,我不知道如何在不完全中断执行的情况下同步这些内核。在我的示例结构中,我想在 CPU (
src_node
) 上执行内核,并使用 CPU (CPU_child
) 和 GPU (GPU_child
) 并行处理输出。
如何确保在完成
GPU_child
之前不执行src_node
而不中断CPU_child
的执行?
据我了解,事件仅在一个上下文中有效,并且不可能与来自不同平台的设备创建共享上下文。我发现很难在网上找到任何关于不同平台系统的信息。这真的不常见吗?我做错了什么吗?
...
cl::Device CPU = ...;
cl::Device GPU = ...;
std::string kernel = ...;
cl::Context CPU_context = cl::Context({CPU});
cl::Context GPU_context = cl::Context({GPU});
cl::CommandQueue CPU_queue(CPU_context, CPU);
cl::CommandQueue GPU_queue(GPU_context, GPU);
cl::Program CPU_program(CPU_context, {kernel});
cl::Program GPU_program(GPU_context, {kernel});
CPU_program.build({CPU});
GPU_program.build({GPU});
cl::Kernel src_node(CPU_program, "kernel");
cl::Kernel CPU_child(CPU_program, "kernel");
cl::Kernel GPU_child(GPU_program, "kernel");
const int N = 10e6;
std::vector<unsigned> input(N, 1);
std::vector<unsigned> immediate(N);
cl::Buffer input_buffer(CPU_context, CL_MEM_USE_HOST_PTR, N * sizeof(unsigned), input.data());
cl::Buffer immediate_buffer(CPU_context, CL_MEM_USE_HOST_PTR, N * sizeof(unsigned), immediate.data());
cl::Buffer output_buffer(CPU_context, CL_MEM_READ_WRITE, N * sizeof(unsigned));
cl::Buffer immediate_buffer_GPU(GPU_context, CL_MEM_COPY_HOST_PTR, N * sizeof(unsigned), immediate.data());
cl::Buffer output_buffer_GPU(GPU_context, CL_MEM_READ_WRITE, N * sizeof(unsigned));
src_node.setArg(0, input_buffer);
src_node.setArg(1, immediate_buffer);
CPU_child.setArg(0, immediate_buffer);
CPU_child.setArg(1, output_buffer);
GPU_child.setArg(0, immediate_buffer_GPU);
GPU_child.setArg(1, output_buffer_GPU);
std::vector<cl::Event> events = { cl::Event() };
CPU_queue.enqueueNDRangeKernel(src_node, cl::NullRange, N, cl::NullRange, NULL, &events[0]);
// This works
CPU_queue.enqueueNDRangeKernel(CPU_child, cl::NullRange, N, cl::NullRange, &events);
// This does not work, how to do this?
GPU_queue.enqueueNDRangeKernel(GPU_child, cl::NullRange, N, cl::NullRange, &events);
...
我可以用这段代码发现很多问题:
immediate_buffer_GPU
在 immediate
甚至有机会通过 src_node
的输出填充它之前充满了 immediate_buffer
的内容。据我所知,如果设备不是来自匹配的平台,因此不能在单一上下文中使用,则您必须“以困难的方式”执行所有同步:您需要显式等待事件在一个上下文中完成,然后在另一个上下文中排队相关操作(包括复制缓冲区)。