将array_view.sync_asynch 等待parallel_for_each完成

will array_view.synchronize_asynch wait for parallel_for_each completion?

本文关键字:parallel for each 等待 完成 asynch array view sync      更新时间:2023-10-16

如果我在concurrency::parallel_for_each循环中操作concurrency::array_view,我的理解是我可以在循环执行时继续在CPU上执行其他任务:

using namespace Concurrency;
array_view<int> av;
parallel_for_each(extent<1>(number),[=](index<1> idx)
{
  // do some intense computations on av
}
// do some stuff on the CPU while we wait
av.synchronize(); // wait for the parallel_for_each loop to finish and copy the data

但是,如果我想不等待并行 for 循环,而是尽快开始从 GPU 复制数据怎么办。以下方法是否有效?

using namespace Concurrency;
array_view<int> av;
parallel_for_each(extent<1>(number),[=](index<1> idx)
{
  // do some intense computations on av
}
// I know that we won't be waiting to synch when I call this, but will we be waiting here
// until the data is available on the GPU end to START copying?
completion_future waitOnThis = av.synchronize_asynch();
// will this line execute before parallel_for_each has finished processing, or only once it
// has finished processing an the data from "av" has started copying back?
completion_future.wait();

我在《飞蛾》上读到了这个话题,但在阅读以下内容后,我并没有真正明智:

请注意,parallel_for_each执行时好像与 调用代码,但实际上它是异步的。即一旦 parallel_for_each调用,内核已传递给 运行时,some_code_B区域继续执行 CPU 线程,而内核并行由 GPU 执行 线程。但是,如果您尝试访问(数组或array_view)数据 您在 some_code_B 区域的 lambda 中捕获的代码 将阻止,直到结果可用。因此正确的 语句:parallel_for_each在以下方面是同步的 可见的副作用,但实际上是异步的。

我不喜欢这种解释方式。更好的考虑方法是parallel_for_each队列对 GPU 起作用,因此它几乎立即返回。在排队的工作完成之前,CPU 端代码可以通过多种方式进行阻塞,例如,显式调用 synchronize 或从parallel_for_each中使用的array_view实例之一访问数据

using namespace concurrency;
array_view<int> av;
parallel_for_each(extent<1>(number),[=](index<1> idx)
{
  // Queue (or schedule if you like) some intense computations on av
}

主机代码现在可以执行。AMP 计算可能已经开始,也可能尚未开始。如果这里的代码访问av那么它将阻塞,直到 GPU 上的工作完成并且av中的数据已经写入并且可以与主机内存同步。

这是一个未来,所以它也是一个预定的任务。不保证在任何特定点执行。如果它被调度,那么它将阻塞它正在运行的线程,直到av与主机内存正确同步(如上所述)。

completion_future waitOnThis = av.synchronize_asynch();

可以在此处执行更多主机代码。如果主机代码访问av则它将阻塞,直到parallel_for_each完成(如上所述)。在某个时候,运行时将执行将来和阻塞,直到av与主机内存同步。如果它是可写的并且已被更改,那么它将被复制回主机内存。

completion_future.wait();

wait的调用将阻止,直到将来完成(在调用wait之前,不能保证任何内容已实际执行)。此时,您可以保证 GPU 计算已完成,并且可以在 CPU 上访问av

话虽如此,增加waitOnThis未来似乎使事情过于复杂。

array_view<int> av;
parallel_for_each(extent<1>(number),[=](index<1> idx)
{
  // do some intense computations on av on the GPU
}
// do some independent CPU computation here.
av.synchronize();
// do some computation on the CPU that relies on av here.

MSDN 文档在这个主题上不是很好。下面的博客文章更好。在同一博客上的异步 API 上还有其他一些帖子。