1

如果我concurrency::array_view在一个concurrency::parallel_for_each循环中被操作,我的理解是我可以在循环执行时继续 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();

我在The Moth上阅读了有关此主题的信息,但在阅读了以下内容后,我并没有真正变得更聪明:

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

4

1 回答 1

2

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

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 计算已完成并且av可以在 CPU 上访问。

说了这么多,添加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 的其他帖子。

于 2013-11-11T07:52:24.587 回答