1

是否有一个特殊的“等待事件”功能可以在设备端同时等待 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 的网站上没有任何示例。

4

2 回答 2

1

你问了太多问题,表达了太多变种,无法为你提供唯一的解决方案,所以我会尽量回答一般性的,你可以找出最合适的解决方案。

如果队列绑定到相同的上下文(可能绑定到同一上下文中的不同设备),则可以通过事件同步它们。即,您可以从提交到一个队列的命令中获取事件,并使用此事件来同步提交到另一个队列的命令,例如

queue1.enqueue(comm1, /*dependency*/ NULL, /*result event*/ &e1);
queue2.enqueue(comm2, /*dependency*/ &e1, /*result event*/ NULL);

在本例中,comm2将等待comm1完成。

如果您需要先将命令排入队列但不允许它们被执行,您可以创建用户事件 ( clCreateUserEvent) 并手动发出信号 ( clSetUserEventStatus)。允许实现在命令入队后立即处理命令(驱动程序不需要等待flush)。

屏障对于您的目的来说似乎有点过分,因为它等待之前提交到队列的所有命令。您可以真正使用clEnqueueMarker它来等待所有事件并提供一个事件用于其他命令。

据我所知,如果您不再需要该活动,您可以随时保留该活动。如果出于内部目的需要,实施应延长事件的生命周期。

我不知道是什么enqueueWaitList

题外话:如果您需要计算之间的重要依赖关系,您可能需要考虑TBB 流图opencl_node. 使用opencl_node事件进行同步,并尽可能避免“主机-设备”同步。但是,为同一设备使用多个队列可能会很棘手。

据我所知,Intel HD Graphics 530 支持乱序队列(至少在主机端)。

于 2016-09-08T13:07:50.360 回答
1

你让它变得比它需要的更难。在写队列上接受一个事件。将其用作计算队列上的计算条件,并获取另一个事件。将其用作读取队列中读取的条件。没有理由强制任何其他同步。注意:我对规范的解释是,在使用该事件作为另一个队列的条件之前,您必须在从中获取事件的队列上进行 clFlush。

于 2016-09-08T22:21:31.250 回答