c++ - 如何在系统上使用并行 std::for_each不见了?
问题描述
这个 C++17 片段在较新版本的 G++ 中运行良好
std::for_each(std::execution::par_unseq, container.begin(), container.end(), [&](const auto& element) {
// do something with element... or don't. whatever.
});
例如,当您尝试将该代码移植到具有 G++ 8.3.0(截至 2020 年 12 月)的当前 Debian(Stable)发行版时,您会发现自己正在阅读以下错误消息:
fatal error: execution: File not found
#include <execution>
^~~~~~~~~~~
一个明显的依赖于__has_include
涉及宏的解决方案是:
#if __has_include(<execution>)
#include <execution>
#define PAR_UNSEQ std::execution::par_unseq,
#else
#define PAR_UNSEQ
#endif
std::for_each(PAR_UNSEQ container.begin(), container.end(), [&](const auto& element) {
// do something with element... or don't. whatever.
});
这编译得很好,但在我看来有两个主要问题:
- 它不是系统上的并行,没有
<execution>
标题和 - 那个宏不是我喜欢看的东西。
那么有没有更好的方法呢?
或者,如果没有,至少有一个宏解决方案实际上是并行的for_each
?
解决方案
<execution>
是在 gcc 9(我认为是 9.1)中添加的,但您可以直接使用底层库Intel® oneAPI 线程构建块或tbb
简称。这有点麻烦,但是如果您链接到下面的内容,则可以在 gcc 8.3 中使用-ltbb
(即使在包含的较新 gcc 版本中,您也需要链接<execution>
)。我的示例使用tbb::parallel_for
的是 gcc:sstd::for_each
最有可能使用的。
我认为它解决了最重要的部分,那就是它在没有<execution>
标头的系统上是并行的。
#if __has_include(<execution>)
#include <execution>
#else
#include "tbb/tbb.h"
// define a support class for using with tbb::paralell_for
template<typename C, typename Func>
class ApplyFunc {
public:
ApplyFunc(const C& container, Func func) : c(container), f(func) {}
// the function that will be called for each block
void operator()(const tbb::blocked_range<size_t>& r) const {
for(size_t i = r.begin(); i != r.end(); ++i)
f(c[i]); // the function you'd like to apply to each element
}
private:
const C& c;
Func f;
};
#endif
// A function to call std::for_each or the tbb version
template<typename C, typename Func>
decltype(auto) myfor_each(const C& container, Func func) {
#if __has_include(<execution>)
std::for_each(std::execution::par, container.begin(), container.end(), func);
#else
tbb::parallel_for(tbb::blocked_range<size_t>(0, container.size()),
ApplyFunc(container, func));
#endif
}
int main() {
// example usage
std::vector<int> container;
myfor_each(container, [](auto& e) { do something eith e });
}
推荐阅读
- office-js - 在 Word 加载项中用新段落替换段落
- spring-batch - 在 Spring Batch 作业中使用 Java ProcessBuilder - Tasklet
- excel - 如何从多个表创建数据透视表
- c++ - 正确声明嵌套模板结构。如何?
- sql - 多次返回时只返回最后一个结果集,多选
- c++ - 排序功能实现中的分段错误
- google-people-api - Google people.api,如何获取特定组的成员?
- sql - WHERE 条件是否适用于所有联接的结果,还是需要在联接内部应用?
- python - 使用 Openpyxl 查找和替换
- reactjs - Redux 状态第一次没有更新