我想使用std::views
为并行化的基于索引的for循环设置一个简单的解决方案。
对于顺序运行,代码看起来像这样:
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;
}
这个很好用。我使用的是std::for_each()
的标准版本,而不是ranges
名称空间中的版本,因为它们没有执行策略。现在是平行版本。唯一的区别:
for_each(execution::par, r.begin(), r.end(), [&](int i) {v[i] = distr(eng); });
MSVC给出错误:
error C2338: Parallel algorithms require forward iterators or stronger
我在这里发现了一个类似的问题: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;
然而,我仍然面临着错误
error C2338: Parallel algorithms require forward iterators or stronger.
有人知道这个问题是否有解决方案吗?
3条答案
按热度按时间qhhrdooz1#
views::iota
的迭代器operator*()
的返回类型 * 不是 * 引用类型而是值类型,这使得它 * 不是 * 前向迭代器而是C17中的输入迭代器。由于C17并行算法需要前向迭代器,因此不能将其应用于views::iota
。有人知道这个问题是否有解决方案吗?
已经有一篇论文p2408r4解决了这个问题,所以在标准中没有简单的解决方案,直到它被采用。
vu8f3i0k2#
p2408现在被C++23采用。在MSVC 19.34(VS 17.4)或更高版本中,如果打开
/std:c++latest
(/std:c++20
也可以工作),代码将编译。示例du7egjpx3#
也许只是一个小小的更新。如前所述,代码不能用MSVC编译。然而,这段代码可以用g++-11编译,因为libstd++不对迭代器类别进行任何预先检查。但是,代码总是串行运行,而不管执行策略如何。
重要提示:以下只是我的建议,如果我错了,请纠正我。如果你仍然想实现一个简单的并行化的基于索引的
for
循环,你可以使用STL容器而不是视图:我们现在没有视图,而是将索引存储在
vector<int>
中。这当然伴随着内存和运行时开销,因为必须为容器分配内存,并且必须用索引填充容器。实际的函数可能如下所示: