c++ - 在并行算法中使用 ranges::view::iota

标签 c++ c++17 stl-algorithm range-v3 c++20

由于没有基于索引的parallel for algorithm , 我想知道 ranges::view::iota可以与std::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; });

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

iota_view<I, Bound>::iterator::iterator_category is defined as follows:

(1.1) — If I models Advanceable, then iterator_category is random_access_iterator_tag.

(1.2) — Otherwise, if I models Decrementable, then iterator_category is bidirectional_iterator_tag.

(1.3) — Otherwise, if I models Incrementable, then iterator_category is forward_iterator_tag.

(1.4) — Otherwise, iterator_category is input_iterator_tag.

上面的代码是否正确?使用 iota_view 是否有任何性能损失?这条路?


编辑:我用 range-v3 做了一些测试, cmcstl2和英特尔的 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’)

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

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

最佳答案

在深入研究标准草案后,恐怕答案是否定的:使用起来并不严格符合标准 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);

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

If an algorithm's template parameter is named ForwardIterator, ForwardIterator1, or ForwardIterator2, the template argument shall satisfy the Cpp17ForwardIterator requirements.

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

然而,在实践中我希望实现将使用 std::iterator_traits::iterator_category 来分派(dispatch) 算法的适当重载,正如 PSTL 似乎所做的那样。因此,我相信 OP 中的示例代码会按预期工作。 cmcSTL2 不起作用的原因可能是使用的 iterator_category 属于 __stl2 namespace而不是 std 的。

关于c++ - 在并行算法中使用 ranges::view::iota,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51185974/

相关文章:

c++ - 无法使用 std::cout 打印/输出任何内容

c++ - 如何重载 == 运算符而不使其成为友元函数?

c++ - 非 constexpr 变体成员调用在 constexpr 类成员函数内进行条件编译 - 为什么?

c++ - 在非唯一集合上使用 erase-remove 习语

c++ - 内存访问冲突 C++ Borland

c++ - 在 Visual Studio 中构建 C++ 项目不会创建任何文件

c++ - 如何使用自定义删除器创建 unique_ptr 数组?

c++ - 将 std::any 转换为未知类型

c++ - Std::copy 和 std::ostream_iterator 使用重载函数打印值

c++ - std::sort ( 来自 <algorithm> ) 崩溃