是否有可能将OpenCL内核的执行延迟到提交所有内核之后?

是否有可能将OpenCL内核的执行延迟到提交所有内核之后?,opencl,Opencl,我有一个程序(将细节抽象出来)看起来像这样: std::vector<cl::Event> events; for (uint32_t x = 0; x < image_size.x; x += 32) { for (uint32_t y = 0; y < image_size.y; y += 32) { events.emplace_back(); cl::Event * event_ptr = &events.back(

我有一个程序(将细节抽象出来)看起来像这样:

std::vector<cl::Event> events;
for (uint32_t x = 0; x < image_size.x; x += 32) {
    for (uint32_t y = 0; y < image_size.y; y += 32) {
        events.emplace_back();
        cl::Event * event_ptr = &events.back();
        cl::NDRange range{ cl::size_type(std::min(image_size.x - x, kernel_size)), cl::size_type(std::min(image_size.y - y, kernel_size)) };
        cl::NDRange offset{ cl::size_type(x), cl::size_type(y) };
        queue.enqueueNDRangeKernel(kernel, offset, range, {}, nullptr, event_ptr);
    }
}
但在我的测试中,我发现当临界数量的事件排队时,
enqueueNDRangeKernel
将开始阻塞,并且事件将在我仍试图让它们排队时运行。有没有办法阻止任何内核运行,直到我明确希望它们启动?差不多

//PSEUDOCODE
cl::waitEvent trigger;
queue.enqueueWaitEvent(&trigger);

std::vector<cl::Event> events;
for (uint32_t x = 0; x < image_size.x; x += 32) {
    for (uint32_t y = 0; y < image_size.y; y += 32) {
        events.emplace_back();
        cl::Event * event_ptr = &events.back();
        cl::NDRange range{ cl::size_type(std::min(image_size.x - x, kernel_size)), cl::size_type(std::min(image_size.y - y, kernel_size)) };
        cl::NDRange offset{ cl::size_type(x), cl::size_type(y) };
        queue.enqueueNDRangeKernel(kernel, offset, range, {}, nullptr, event_ptr);
    }
}

trigger.release(); //All other events behind this event now start running.
/*...*/
//伪代码
cl::waitEvent触发器;
queue.enqueueWaitEvent(&trigger);
向量事件;
对于(uint32\u t x=0;x

但我不知道OpenCL中是否存在这样的机制,或者该语法是什么样子。我知道我可能可以在Vulkan中实现此功能,但我的目标是那些没有Vulkan驱动程序支持的旧硬件。

您可以尝试用户事件。准备一个用户事件和一个标记以等待它作为队列的第一项,然后将任意多个命令排队,刷新命令队列以确保队列正在推送到gpu,然后当您需要同时推送到所有gpu时,触发用户事件。如果是opencl 2.x,您可以使用原子和svm从主机端在虚拟内核中锁定,然后再次从主机上释放它。为什么要在许多32x32块中处理图像?你不能用一个大的全局工作规模来处理整个事情吗?第二,如果您有一个顺序命令队列,并且您正在将许多事情排队,那么您只需要从最后一个事件中获取一个事件。为较早的内核获取事件没有任何价值。@Dithermaster很明显,我提供的代码是示例代码,用于替代更复杂的代码。您可以让第一个或所有内核等待用户事件,并在排队循环后仅触发用户事件,但是,如果您的运行时对阻塞前可以排队的项目数量有一些限制,那么您的enqeuue循环将被阻塞,并且您将永远无法触发用户事件。请参阅clCreateUserEvent。
//PSEUDOCODE
cl::waitEvent trigger;
queue.enqueueWaitEvent(&trigger);

std::vector<cl::Event> events;
for (uint32_t x = 0; x < image_size.x; x += 32) {
    for (uint32_t y = 0; y < image_size.y; y += 32) {
        events.emplace_back();
        cl::Event * event_ptr = &events.back();
        cl::NDRange range{ cl::size_type(std::min(image_size.x - x, kernel_size)), cl::size_type(std::min(image_size.y - y, kernel_size)) };
        cl::NDRange offset{ cl::size_type(x), cl::size_type(y) };
        queue.enqueueNDRangeKernel(kernel, offset, range, {}, nullptr, event_ptr);
    }
}

trigger.release(); //All other events behind this event now start running.
/*...*/