简体   繁体   English

与 std::for_each 和 std::views::iota 并行循环

[英]Parallel for loop with std::for_each and std::views::iota

I want to set up an easy workaround for parallelized index-based for-loops using std::views .我想使用std::views为并行化的基于索引的 for 循环设置一个简单的解决方法。

For running in sequence the code looks like this:对于按顺序运行,代码如下所示:

int main() {

    //pseudo-random numbers

    random_device rd;
    default_random_engine eng(rd());
    uniform_int_distribution<int> distr(0, 100);

    auto r = ranges::views::iota(0, 10);
    vector<double> v(10, 1);
    for_each(r.begin(), r.end(), [&](int i) {v[i] = distr(eng); });
    for (auto&& i : v) cout << i << " "; cout << endl;
}

This works fine.这很好用。 I am using the standard version of std::for_each() , not the one in the ranges namespace, because those don't have the execution policies.我使用的是std::for_each()的标准版本,而不是ranges命名空间中的版本,因为它们没有执行策略。 Now the parallel version.现在是水货版。 Only difference:唯一区别:

for_each(execution::par, r.begin(), r.end(), [&](int i) {v[i] = distr(eng); });

MSVC gives an error: MSVC 报错:

error C2338: Parallel algorithms require forward iterators or stronger

I found a similar issue here: Using ranges::view::iota in parallel algorithms and I implemented the solution offered there:我在这里发现了一个类似的问题: Using ranges::view::iota in parallel algorithms我实现了那里提供的解决方案:

    auto r = views::iota(0) | views::take(10);
    vector<double> v(10, 1);
    auto input_range = ranges::common_view(r);

    for_each(execution::par, ranges::begin(input_range), ranges::end(input_range), [&](int i) {v[i] = distr(eng); });
    for (auto&& i : v) cout << i << " "; cout << endl;

However, I am still facing the error但是,我仍然面临错误

error C2338: Parallel algorithms require forward iterators or stronger.

Does someone know whether there is a solution to this issue?有人知道这个问题是否有解决方案吗?

The return type of operator*() of views::iota 's iterator is not a reference type but a value type, which makes it not a forward iterator but an input iterator in C++17. Since the C++17 parallel algorithm requires forward iterators, you cannot apply it to views::iota . views::iota的迭代器operator*()的返回类型不是引用类型而是值类型,这使得C++17中的不是正向迭代器而是输入迭代器。由于C++17并行算法需要正向迭代器,你不能将其应用于views::iota

Does someone know whether there is a solution to this issue?有人知道这个问题是否有解决方案吗?

There is already a paper p2408r4 addressing this issue, so there is no simple solution in the standard until it is adopted.已经有一篇论文p2408r4解决了这个问题,所以在它被采用之前,标准中没有简单的解决方案。

Maybe just a small update.也许只是一个小更新。 As was pointed out, the code does not compile with MSVC.正如所指出的,该代码无法使用 MSVC 进行编译。 The code does, however, compile with g++-11 since libstd++ does not do any up-front checking of the iterator category.然而,代码确实使用 g++-11 编译,因为 libstd++ 不对迭代器类别进行任何前期检查。 However, the code runs always in serial, irrespective of the execution policy.但是,无论执行策略如何,代码始终以串行方式运行。

Important: The following is just my suggestion, please correct me if I am wrong.重要提示:以下只是我的建议,如有错误请指正。 If you still want to implement an easy parallelized index-based for loop, you can make use of STL containers rather than views:如果您仍想实现一个简单的基于并行索引的for循环,您可以使用 STL 容器而不是视图:

template<typename Policy, typename func>
void parallel_for(Policy p, int first, int last, func f) {

    vector<int> idxs(last - first);
    iota(idxs.begin(), idxs.end(), first);
    for_each(p, begin(idxs), end(idxs), f);
}

Instead of having a view, we now just store the indices in a vector<int> .我们现在不再使用视图,而是将索引存储在vector<int>中。 This of course comes with a memory and runtime overhead since memory for the container must be allocated and the container must be filled with the indices.这当然带有 memory 和运行时开销,因为必须为容器分配 memory 并且必须用索引填充容器。 The function in action could look like this:实际中的 function 可能如下所示:

int fib(int i) {
    if (i <= 1)
        return i;
    return fib(i - 1) + fib(i - 2);
}

int main() {

    vector<vector<double>> mat(100, vector<double>(100, 1));

    parallel_for(execution::par, 0, mat.size(), [&mat](int i) {

        for (int j = 0; j < mat[i].size(); ++j) {
            mat[i][j] = fib(40);
        }
        });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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