met*_*fox 5 c++ stl-algorithm range-v3 c++17 c++20
由于在c ++ 17中没有基于索引的算法并行,我想知道是否可以结合使用来模拟。那是: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_category是random_access_iterator_tag。(1.2) -否则,如果
I模型Decrementable,然后iterator_category是bidirectional_iterator_tag。(1.3) -否则,如果
I模型Incrementable,然后iterator_category是forward_iterator_tag。(1.4)-否则
iterator_category为input_iterator_tag。
上面的代码正确吗?使用iota_view这种方式是否会降低性能?
编辑:我已经使用range-v3,cmcstl2和Intel的PSTL进行了一些测试。
使用range-v3,以上示例无法使用GCC 8进行编译。编译器抱怨begin并end具有不同的类型:
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)。
在深入研究标准草案后,恐怕答案是否定的:
ranges::iota_view在for_each.
的并行重载for_each声明为[alg.foreach]:
Run Code Online (Sandbox Code Playgroud)template<class ExecutionPolicy, class ForwardIterator, class Function> void for_each(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Function f);
另一方面,在[algorithms.requirements]中我们找到了约束:
如果算法的模板参数名为
ForwardIterator、ForwardIterator1或ForwardIterator2,则模板参数应满足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空间。
| 归档时间: |
|
| 查看次数: |
1964 次 |
| 最近记录: |