程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了C++:如何在 n 个范围上并行化 n 元运算?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决C++:如何在 n 个范围上并行化 n 元运算??

开发过程中遇到C++:如何在 n 个范围上并行化 n 元运算?的问题如何解决?下面主要结合日常开发的经验,给出你关于C++:如何在 n 个范围上并行化 n 元运算?的解决方法建议,希望对你解决C++:如何在 n 个范围上并行化 n 元运算?有所启发或帮助;

两个范围内的二元运算可以通过这种方式并行化:

#include <Cassert>
#include <algorithm>
#include <vector>
#include <execution>

std::vector<int> add(const std::vector<int>& A,const std::vector<int>& B) {
    assert(A.size() == B.size());
    std::vector<int> c;
    C.reserve(A.size());
    std::transform(std::execution::par_unseq,A.begin(),A.end(),B.begin(),std::BACk_inserter(C),std::plus<>{});
    return c;
}

我想通过求和 n 个参数(或任何 n 元运算)将其扩展到 n 个范围。范围的数量 n 在编译时是未知的。

std::transform 不提供这样做。我该怎么办

我想要这样的东西:

#include <algorithm>
#include <Cassert>
#include <vector>
#include <ranges>

std::vector<int> addn (const std::vector<std::vector<int>>& Rs) {

    const std::size_t n = Rs[0].size();
    assert(std::ranges::all_of(Rs,[&n](const auto& R){return R.size() == n;}));
    std::vector<int> res(n);
    // want to parallelize
    for (std::size_t i = 0; i < n; ++i) {
        for (const auto& R : Rs) {
            res[i] += R[i];
        }
    }
    return res;
}

解决方法

如果您有一个嵌套的 for 循环,并且想将其转换为使用 STL 算法,那么通常的技巧是嵌套 STL 算法。如果您想对每一行求和,那么 for 循环将如下所示:

for (auto row: Rs) {
    int sum = 0;
    for (auto col: row)
        sum += R;
    res.push_BACk(sum);
}

然后转换为算法会相对容易:内循环可以用std::accumulate代替:

for (auto row: Rs) {
    res.push_BACk(std::accumulate(row.begin(),row.end(),0);
}

然后可以将外循环转换为对 std::transform() 的调用。最终的函数看起来像:

std::vector<int> sum_each_row(const std::vector<std::vector<int>>& Rs) {
    const std::size_t n = Rs.size();
    std::vector<int> res(n);

    std::transform(std::execution::par_unseq,Rs.begin(),Rs.end(),res.begin(),[](auto&& row) {
        return std::accumulate(row.begin(),0);
    });

    return res;
}

您可以使用 std::reduce(std::execution::par_unseq,...) 代替 std::accumulate() 进行进一步的并行化,但很可能只需将外循环并行化就足够了。

然而,如果我们想对每一列求和,事情就会变得更加混乱。我们可以做的是对 Rs 中第一行的元素进行并行变换,并尝试获取该元素的索引,如下所示:

std::transform(std::execution::par_unseq,Rs[0].begin(),Rs[0].end(),[&](auto&& col) {
    size_t i = &col - &Rs[0].front();
    ...
}

一旦我们有了列索引 i,我们可以手动执行 for 循环来对该列求和,或者再次使用类似的技巧来使用 STL 算法。这是一个可能的实现:

std::vector<int> sum_each_column(const std::vector<std::vector<int>>& Rs) {
    const std::size_t n = Rs[0].size();
    std::vector<int> res(n);

    std::transform(std::execution::par_unseq,[&](auto&& col) {
        size_t i = &col - &Rs[0].front();
        return std::transform_reduce(Rs.begin(),std::plus<>(),[i](auto&& row) {
            return row[i];
        });
    });

    return res;
}

大佬总结

以上是大佬教程为你收集整理的C++:如何在 n 个范围上并行化 n 元运算?全部内容,希望文章能够帮你解决C++:如何在 n 个范围上并行化 n 元运算?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。