简体   繁体   English

如何在系统上使用并行 std::for_each<execution> 不见了?</execution>

[英]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:这编译得很好,但在我看来有两个主要问题:

  • It is not a parallel for on systems, that don't have the <execution> header and对于没有<execution> header 和
  • that macro is not something I enjoy looking at.那个宏不是我喜欢看的东西。

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 Blockstbb 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM