在并行算法中使用range :: view :: iota

met*_*fox 5 c++ stl-algorithm range-v3 c++17 c++20

由于在没有基于索引的算法并行,我想知道是否可以结合使用来模拟。那是:ranges::view::iotastd::for_each

using namespace std;

constexpr int N= 10'000'000;
ranges::iota_view indices(0,N);
vector<int> v(N);

for_each(execution::par_unseq,indices.begin(),indices.end(),[&](int i) { v[i]= i; });
Run Code Online (Sandbox Code Playgroud)

iota_view似乎提供了对适当类型的随机访问([range.iota.iterator]):

iota_view<I, Bound>::iterator::iterator_category 定义如下:

(1.1) -如果I模型Advanceable,然后iterator_categoryrandom_access_iterator_tag

(1.2) -否则,如果I模型Decrementable,然后iterator_categorybidirectional_iterator_tag

(1.3) -否则,如果I模型Incrementable,然后iterator_categoryforward_iterator_tag

(1.4)-否则iterator_categoryinput_iterator_tag

上面的代码正确吗?使用iota_view这种方式是否会降低性能?


编辑:我已经使用range-v3cmcstl2和Intel的PSTL进行了一些测试。

使用range-v3,以上示例无法使用GCC 8进行编译。编译器抱怨beginend具有不同的类型:

deduced conflicting types for parameter ‘_ForwardIterator’ (‘ranges::v3::basic_iterator<ranges::v3::iota_view<int, int> >’ and ‘ranges::v3::default_sentinel’)
Run Code Online (Sandbox Code Playgroud)

使用cmcstl2,代码可以干净地编译,但不会并行运行。在我看来,它回落到了顺序版本,可能是因为某种程度上不满足前向迭代器的要求(https://godbolt.org/z/yvr-M2)。

有一个与PSTL有关的问题(https://github.com/intel/parallelstl/issues/22)。

met*_*fox 6

在深入研究标准草案后,恐怕答案是否定的: ranges::iota_viewfor_each.

的并行重载for_each声明为[alg.foreach]

template<class ExecutionPolicy, class ForwardIterator, class Function>
  void for_each(ExecutionPolicy&& exec,
                ForwardIterator first, ForwardIterator last,
                Function f);
Run Code Online (Sandbox Code Playgroud)

另一方面,在[algorithms.requirements]中我们找到了约束:

如果算法的模板参数名为ForwardIteratorForwardIterator1ForwardIterator2,则模板参数应满足Cpp17ForwardIterator要求。

正如 Billy O'Neal 在我在问题中发布的链接之一中指出的,合理的实现ranges::iota_view::iterator不太可能满足“相等迭代器引用同一对象”前向迭代器要求[iterator.cpp17]。因此,根据我的理解,ranges::iota_view::iterator不会满足Cpp17ForwardIterator 的要求,对于 eg 也是如此 boost::counting_iterator

然而,在实践中,我希望实现将用于调度std::iterator_traits::iterator_category算法的适当重载,就像 PSTL 似乎所做的那样。因此,我相信OP中的示例代码将按预期工作。cmcstl2 不起作用的原因可能是所使用的iterator_category属于名称空间__stl2不是名称std空间。