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.
因此,要么是运行时
f(i)将在主线程中(在最终循环内)顺序执行一些调用.这两个选项似乎效率都低于OpenMP的效率(创建许多任务并在固定数量的线程中同时运行它们).
有没有办法获得与OpenMP任务提供的C++线程相同的行为?
UPDATE
我使用以下代码进行了一些测量:使用GCC 7.2编译的12C Xeon E5 CPU上的https://wandbox.org/permlink/gLCFPr1IjTofxwQh和-O2:
(平均来自几次运行).他们似乎实际上是一样的.
但是,我也尝试过相同的500,000个任务(n)和1000个迭代(m),然后时间差别很大:
更新2
我测量了创建一个新线程的次数(按照这个插入pthread_create调用的答案:https://stackoverflow.com/a/3709027/580083):
第一个实验(20,000个任务,20,000个迭代):
第二个实验(500,000个任务,1000个迭代):
你的分析很不错,但我认为.net中的线程池存在漏洞std::async。
OpenMP确实使用固定的、用户控制的线程数量,可以非常灵活地执行任务。untied任务甚至可以在线程之间移动,尽管这在实践中似乎没有得到很好的支持。
是的,根据C++11标准,实现必须选择std::launch::async或std::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并共享测量代码。
| 归档时间: |
|
| 查看次数: |
1732 次 |
| 最近记录: |