C++异步与OpenMP任务

Dan*_*ica 8 c++ asynchronous task openmp c++11

在OpenMP中,我可以创建如下的一堆任务,并使用一些固定数量的线程异步运行它们:

#pragma omp parallel
{
   #pragma omp single 
   {
      for (int i = 0; i < 1000; i++) {
         #pragma omp task
         f(i);
}  }  }
Run Code Online (Sandbox Code Playgroud)

在C++ 11中,我可以做一些不完全相同的 事情std::async:

std::vector<std::future> futures;
for (int i = 0; i < 1000; i++) {
   auto fut = std::async(f, i);
   futures.push_back(std::move(fut));
}
...
for (auto & fut : futures) {
  auto res = fut.get();
  // do something with res
}
Run Code Online (Sandbox Code Playgroud)

我担心的是效率.如果我是正确的,在OpenMP中,任务存储在某个任务池中,然后分发给线程(由OpenMP运行时自动分配).

在C++中,在调用时std::async,运行时决定是f(i)在新线程中异步运行还是将其运行推迟到调用点std::future::get.

因此,要么是运行时

  1. 创建1000个线程并同时运行它们,
  2. 或者创建更少的线程,但是然后f(i)将在主线程中(在最终循环内)顺序执行一些调用.

这两个选项似乎效率都低于OpenMP的效率(创建许多任务并在固定数量的线程中同时运行它们).

有没有办法获得与OpenMP任务提供的C++线程相同的行为?

UPDATE

我使用以下代码进行了一些测量:使用GCC 7.2编译的12C Xeon E5 CPU上的https://wandbox.org/permlink/gLCFPr1IjTofxwQh-O2:

  1. 具有12个线程的OpenMP运行时:12.2 [s]
  2. C++线程运行时:12.4 [s]

(平均来自几次运行).他们似乎实际上是一样的.

但是,我也尝试过相同的500,000个任务(n)和1000个迭代(m),然后时间差别很大:

  1. 具有12个线程的OpenMP运行时:15.1 [s]
  2. C++ threding运行时:175.6 [s]

更新2

我测量了创建一个新线程的次数(按照这个插入pthread_create调用的答案:https://stackoverflow.com/a/3709027/580083):

第一个实验(20,000个任务,20,000个迭代):

  1. 具有12个线程的OpenMP运行时:11
  2. C++ threding运行时:20,000

第二个实验(500,000个任务,1000个迭代):

  1. 具有12个线程的OpenMP运行时:11
  2. C++ threding runtime:32,744

Zul*_*lan 5

你的分析很不错,但我认为.net中的线程池存在漏洞std::async

OpenMP确实使用固定的、用户控制的线程数量,可以非常灵活地执行任务。untied任务甚至可以在线程之间移动,尽管这在实践中似乎没有得到很好的支持

是的,根据C++11标准,实现必须选择std::launch::asyncstd::launch::deferred。前者必须创建一个std::thread对象,而后者将在线程调用中执行任务的代码wait。但是,标准留下了一个注释(强调我的):

如果此策略与其他策略一起指定,例如使用 的policy值时launch::async | launch::deferred,实现应推迟调用或在无法有效利用更多并发时选择策略

老实说,看不出除了该注释之外的标准措辞如何允许实现推迟决定 - 但该标准似乎实际上鼓励线程池!如果选择的决定launch:async被推迟,这意味着所需的新std::thread线程可以重用现有的执行线程——至少我不明白为什么不这样做。

最初我认为这std::thread也可以实现为绿色线程,这也意味着线程池。但是,线程 [由]管理的标准注释旨在与操作系统线程一对一映射。<thread>

在一天结束时测量以验证您的表现。可能有一个非常糟糕的 OpenMP 实现或一个非常聪明的标准库实现。

This answer to a similar question,提供了一些测量结果,表明高开销std::async并共享测量代码。