【发布时间】:2020-06-09 06:19:48
【问题描述】:
鉴于这段代码:
struct T
{
void f(int const);
};
void f(std::vector<T> &u, std::vector<int> const &v)
{
for (std::size_t i = 0; i < u.size(); ++i)
u[i].f(v[i]);
}
有没有标准的方法来并行化void f(std::vector<T> &u, std::vector<int> const &v) 的主体?
这碰巧奏效了 (https://godbolt.org/z/gRv9Ze):
void f(std::vector<T> &u, std::vector<int> const &v)
{
auto const indices = std::views::iota(0u, u.size()) | std::views::common;
std::for_each(std::execution::par_unseq, std::begin(indices), std::end(indices),
[&](std::size_t const i) { u[i].f(v[i]); });
}
但据报道,依赖这种行为是错误的(参见bug report 还有这个answer)。实际上,这不是并行运行的 (https://godbolt.org/z/MPGdHF):
void f(std::vector<T> &u, std::vector<int> const &v)
{
std::ranges::iota_view<std::size_t, std::size_t> const indices(0u, u.size());
std::for_each(std::execution::par_unseq, std::begin(indices), std::end(indices),
[&](std::size_t const i) { u[i].f(v[i]); });
}
我很确定应该有一种标准方法可以让类似的函数并行运行。我可能错过了一个明显的
算法,但是std::transform在这里似乎不合适,其他的更不合适。
【问题讨论】:
-
第一个示例“这碰巧起作用”--> 根据cppreference:“如果实现无法并行化或矢量化(例如,由于缺乏资源),所有标准执行策略都可能失效回到顺序执行。”第二个示例“确实,这不能并行运行”-> 如您链接的错误报告中一样,将 iota_view 模板参数更改为有符号整数类型以满足要求就可以了。
-
@gkhaos 我知道我可以让它在 GCC 中工作。问题是
iota_view::iterator没有对Cpp17ForwardIterator建模,因此实现静默地回退到顺序版本可能是完美的。事实上,例如,MSVC 团队声称在他们的实现中没有尝试支持此类迭代器:github.com/oneapi-src/oneDPL/issues/22#issuecomment-442180158
标签: c++ c++17 c++20 stl-algorithm