是否有一个特殊的“等待事件”功能可以在设备端同时等待 3 个队列,因此它不会从主机端连续等待所有队列?
是否有要发送到命令队列的检查点命令,以便它必须等待其他命令队列击中相同(垂直)屏障/检查点以等待并从设备端继续,因此不需要主机端往返?
目前,我尝试了两个不同的版本:
clWaitForEvents(3, evt_);
和
int evtStatus0 = 0;
clGetEventInfo(evt_[0], CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(cl_int), &evtStatus0, NULL);
while (evtStatus0 > 0)
{
clGetEventInfo(evt_[0], CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(cl_int), &evtStatus0, NULL);
Sleep(0);
}
int evtStatus1 = 0;
clGetEventInfo(evt_[1], CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(cl_int), &evtStatus1, NULL);
while (evtStatus1 > 0)
{
clGetEventInfo(evt_[1], CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(cl_int), &evtStatus1, NULL);
Sleep(0);
}
int evtStatus2 = 0;
clGetEventInfo(evt_[2], CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(cl_int), &evtStatus2, NULL);
while (evtStatus2 > 0)
{
clGetEventInfo(evt_[2], CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(cl_int), &evtStatus2, NULL);
Sleep(0);
}
第二个要快一些(我从别人那里看到的),两者都是在 3 个刷新命令之后执行的。
查看 CodeXL 分析器结果,第一个在完成点之间等待的时间更长,一些操作似乎甚至没有重叠。第二个显示 3 个完成点都在 3 毫秒内,因此它更快并且更长的部分重叠(同时读取 + 写入 + 计算)。
如果有一种方法可以通过主机端的 1 个等待命令来实现这一点,那么它也必须有一个“刷新”版本,但我找不到。
有没有办法实现下图而不是在每个管道步骤之间添加刷新?
queue1 write checkpoint write checkpoint write
queue2 - compute checkpoint compute checkpoint compute
queue3 - checkpoint read checkpoint read
所有检查点都必须垂直同步,并且在发出信号之前,所有这些操作都不得开始。如:
queue1.ndwrite(...);
queue1.ndcheckpoint(...);
queue1.ndwrite(...);
queue1.ndcheckpoint(...);
queue1.ndwrite(...);
queue2.ndrangekernel(...);
queue2.ndcheckpoint(...);
queue2.ndrangekernel(...);
queue2.ndcheckpoint(...);
queue2.ndrangekernel(...);
queue3.ndread(...);
queue3.ndcheckpoint(...);
queue3.ndread(...);
queue3.ndcheckpoint(...);
queue3.ndread(...);
queue1.flush()
queue2.flush()
queue3.flush()
queue1.finish()
queue2.finish()
queue3.finish()
检查点都在设备端处理,主机端只需要 3 个完成命令(更好,所有队列只需要 1 个完成?)
如何使用“clWaitForEvents(3, evt_);”将 3 个队列绑定到 3 个事件 现在是:
hCommandQueue->commandQueue.enqueueBarrierWithWaitList(NULL, &evt[0]);
hCommandQueue2->commandQueue.enqueueBarrierWithWaitList(NULL, &evt[1]);
hCommandQueue3->commandQueue.enqueueBarrierWithWaitList(NULL, &evt[2]);
如果这个“排队障碍”可以与其他队列交谈,我怎么能做到这一点?在所有队列完成之前,我是否需要保持主机端事件处于活动状态,或者我可以删除它们或稍后重新使用它们?从文档来看,似乎第一个屏障事件可以放入第二个队列,第二个屏障事件可以与第一个事件一起放入第三个,所以可能是这样的:
hCommandQueue->commandQueue.enqueueBarrierWithWaitList(NULL, &evt[0]);
hCommandQueue2->commandQueue.enqueueBarrierWithWaitList(evt_0, &evt[1]);
hCommandQueue3->commandQueue.enqueueBarrierWithWaitList(evt_0_and_1, &evt[2]);
in the end wait for only evt[2] maybe or using only 1 same event for all:
hCommandQueue->commandQueue.enqueueBarrierWithWaitList(sameEvt, &evt[0]);
hCommandQueue2->commandQueue.enqueueBarrierWithWaitList(sameEvt, &evt[1]);
hCommandQueue3->commandQueue.enqueueBarrierWithWaitList(sameEvt, &evt[2]);
where to get sameEvt object?
有人试过这个吗?我是否应该以障碍开始所有队列,以便在我从主机端引发一些事件之前它们不会开始,或者“入队”的延迟执行是 %100 可信任到“直到我刷新/完成”它们才开始?如何从主机向设备引发事件(sameEvt 没有“引发”功能,是 clCreateUserEvent 吗?)?
所有 3 个队列都是有序类型并且在相同的上下文中。并非所有显卡都支持乱序类型。正在使用 C++ 绑定。
还有 enqueueWaitList(是否已弃用?)和 clEnqueueMarker 但我不知道如何使用它们,并且文档在 Khronos 的网站上没有任何示例。