[英]How to use a parallel std::for_each on systems where <execution> is missing?
This C++17 snippet works fine in newer versions of G++这个 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.
});
When you try to port that code to the current Debian (Stable) distribution for instance, which has G++ 8.3.0 (as of 12/2020), you'll find yourself reading the following error message:例如,当您尝试将该代码移植到当前的 Debian(稳定)发行版中,该发行版具有 G++ 8.3.0(截至 2020 年 12 月),您会发现自己正在阅读以下错误消息:
fatal error: execution: File not found
#include <execution>
^~~~~~~~~~~
An obvious solution relying on __has_include
that involves a macro is:依赖于涉及宏的__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.
});
This compiles fine but has 2 major issues in my eyes:这编译得很好,但在我看来有两个主要问题:
<execution>
header and对于没有<execution>
header 和So is there a better way?那么有没有更好的方法呢?
Or if not is there at least a macro solution that actually does a parallel for_each
?或者,如果没有,至少有一个宏解决方案可以实际执行并行for_each
吗?
<execution>
was added in gcc 9 (9.1 I think) but you could use the underlying library, Intel® oneAPI Threading Building Blocks or tbb
for short, directly instead. <execution>
是在 gcc 9(我认为是 9.1)中添加的,但您可以直接使用底层库Intel® oneAPI Threading Building Blocks或tbb
。 It's a little cumbersome but something like the below would work in gcc 8.3 if you link with -ltbb
(which you need to link with even in the newer gcc versions where <execution>
is included).这有点麻烦,但如果您与-ltbb
链接(即使在包含<execution>
的较新的 gcc 版本中也需要链接),类似下面的内容将在 gcc 8.3 中工作。 My example uses tbb::parallel_for
which is what gcc:s std::for_each
most likely also uses.我的示例使用tbb::parallel_for
,这也是 gcc:s std::for_each
最有可能使用的。
It solves, what I believe is, the most important part and that is that it's parallel on systems that don't have the <execution>
header.我相信它解决了最重要的部分,那就是它在没有<execution>
header 的系统上是并行的。
#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 });
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.