我正在寻找一种简单而干净的方式,告诉我的主机,OpenCL中的某些代码会导致错误,并且应该放弃进一步的工作。我(想)知道,尝试,捕获或断言在OpenCL C中不起作用。此外,内核必须被定义为非返回函数,因此简单的错误代码返回也不在图像之外。我唯一的想法是在主机和内核之间传递一个cl_mem对象,并在内核入队或启动之间检查它的值,它以某种方式强制执行非常强大的序列化。是否有更好的想法,也许是使用事件?
答案 0 :(得分:3)
为了不导致序列化,请使用异步解决方案。每个内核都使用一个cl_mem对象,如果它想告诉主机端关闭,它会写一个sentinal值。当主机稍后检测到此情况时,它会停止排队工作。因为这是异步的,所以一些额外的工作项可能会在写入和读取之间排队,您的系统将需要处理这种情况。您可能需要一个cl_mem对象的环形缓冲区,因为您需要在主机上读取或映射它们以检查它们的内容,并且您不希望阻止任何内核执行此操作。
在OpenCL 2.x中,您可以使用管道进行此通信,但我没有使用它们,因此我无法提供有关此解决方案的更多详细信息。
答案 1 :(得分:3)
如果你需要类似的东西,比如
for(i 0 to N)
{
do work (i)
error ? break;
}
以平行的方式,
int threadId=get_global_id(0);
// a broadcast read(for a new gpu) so no performance hit
mem_fence(CLK_GLOBAL_MEM_FENCE_READ)
if(error[0]==0) // or use atomic_add(&error[0],0) to read atomically(when total number of threads is low like thousands)
{
do work (threadId);
error? atomic_add(&error[0],errCode)
mem_fence(CLK_GLOBAL_MEM_FENCE_WRITE)
}
所以至少你在线程组级保存周期,如果在原子错误写入后它们启动,应该让后来的线程快速完成。原子操作很慢但错误处理应该使它不那么重要吧?同样取决于设备类型和驱动程序,它可能需要在原子写入和正确的非原子读取之间至少数千个线程,因此对于一百万个线程它可能是有效的但是对于一千个线程,您应该使用原子读取(原子添加)使用零值)因此每个线程将在实际工作开始之前添加额外的周期,但至少其延迟可能会被大量计算隐藏。
如果您有多个设备需要相互通知错误,则应使用USE_HOST_PTR错误缓冲区直接在主机内存上读取/写入错误代码,而不是使用设备内存。这可能不如设备内存高,因为错误缓冲区不会被缓存,并且将远离设备,因此可能是5GB / s的pci-e带宽瓶颈,而不是5TB / s的设备内存(假设以单周期向所有内核广播) ,最新的显卡)