c++ - 如何在缺少 <execution> 的系统上使用并行 std::for_each?

标签 c++ for-loop c++17

此 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(截至 12/2020)的当前 Debian(稳定)发行版时,您会发现自己阅读以下错误消息:

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.
});

编译正常,但在我看来有 2 个主要问题:

  • 对于没有<execution> 的系统,它不是并行的标题和
  • 我不喜欢看那个宏。

那么有没有更好的办法呢?

或者,如果没有,至少有一个宏解决方案实际上执行并行 for_each

最佳答案

<execution>已添加到 gcc 9(我认为是 9.1)中,但您可以使用底层库 Intel® oneAPI Threading Building Blockstbb简而言之,直接代替。这有点麻烦,但如果您链接到 -ltbb,类似下面的内容将在 gcc 8.3 中工作。 (即使在包含 <execution> 的较新 gcc 版本中,您也需要链接)。我的示例使用 tbb::parallel_for 这就是 gcc:s std::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 });
}

关于c++ - 如何在缺少 <execution> 的系统上使用并行 std::for_each?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65385103/

相关文章:

c++ - QT中如何将xml节点数据转化为字符串

javascript - 有没有更好的方式来写这个,或者更短更紧凑的方式

java - 快速排序多线程

javascript - 制作字符串模式

c++ - 将参数省略复制为返回值

c++ - 保证复制清除如何工作?

c++ - 将 C++ 宏重写为函数等

c++ - 函数返回值错误

数组名称的 C++ 值

c++ - 分配器感知 `std::array` 风格的容器?