【问题标题】:Parallel algorithm to sum-assign the elements of a vector to the elements of another one将一个向量的元素和分配给另一个向量的元素的并行算法
【发布时间】:2019-05-14 10:34:56
【问题描述】:

考虑:

std::vector<double> u, v;

#pragma omp parallel for
for (std::size_t i = 0u; i < u.size(); ++i)
  u[i] += v[i];

为了用 C++17 并行算法表达类似的代码,我目前找到的解决方案是使用 std::transform 的两个输入范围版本:

std::transform(std::execution::par_unseq,
               std::begin(u), std::end(u), std::begin(v), std::begin(u),
               std::plus())

我根本不喜欢它,因为它绕过了我的类型的 += 运算符,并且在我的实际用例中导致比原始 OpenMP 代码更冗长(长 4 倍)的代码(我不能只使用 @ 987654326@ 因为我必须先对 RHS 范围元素进行操作)。

是否还有其他算法需要我监督?

还要注意,如果我使用 ranges::zip,代码将不会在 GCC 9 中并行运行,因为如果 iterator_category 至少不是 forward_iterator,则 PSTL 后端会退回到顺序算法:https://godbolt.org/z/XGtPwc .

【问题讨论】:

  • @George 是的。在我的真实代码中,我需要使用 lambda。这是我不喜欢的多余冗长的一部分。
  • @George 比较 for (std::size_t i = 0u; i &lt; u.size(); ++i) u[i] += 2 * v[i];std::transform(std::execution::par_unseq, std::begin(u), std::end(u), std::begin(v), std::begin(u), [](auto a, auto b) { return a + 2 * b })
  • @metalfox:您不太可能找到比您现在拥有的更简洁的另一种算法。任何算法都需要至少四个迭代器、调度策略和一个函数对象作为参数。
  • AFAIK &lt;algorithm&gt; 中没有任何内容使用复合分配,它只是复制(或移动)分配
  • 另外,AFAIK std::for_each&lt;algorithm&gt; 中唯一允许通过其输入范围进行修改的东西。

标签: c++ c++17 stl-algorithm


【解决方案1】:

您是否尝试过 tbb::zip_iterator (https://www.threadingbuildingblocks.org/docs/help/reference/iterators/zip_iterator.html)? 它的iterator_categoryrandom_access_iterator

所以代码看起来像

auto zip_begin = tbb::make_zip_iterator(std::begin(u), std::begin(v));
std::for_each(par_unseq, zip_begin, zip_begin + u.size(),
                  [](auto &&x) { std::get<0u>(x) += std::get<1u>(x); });

【讨论】:

  • 太好了!乐于助人
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多