简体   繁体   English

为什么并行for_each需要前向迭代器?

[英]Why does the parallel for_each require forward iterators?

I was designing an iterator that goes over multiple containers and thus has a proxy object as a return type. 我正在设计一个遍历多个容器的迭代器,因此有一个代理对象作为返回类型。 Because of that, the best it can do is to be an input iterator (this is because forward iterators require reference to be an actual reference type, while this isn't true for input iterators as far as I see). 因此,它可以做的最好是成为一个输入迭代器(这是因为前向迭代器需要reference是一个实际的引用类型,而对于输入迭代器来说这是不正确的)。

The (let me say) plain for_each works like a charm with my iterator. (让我说)简单的for_each就像我的迭代器的魅力一样。
However, when I looked at its parallel version, I saw that it accepts only forward iterators. 但是,当我查看它的并行版本时,我看到它只接受前向迭代器。 Therefore I cannot use a complex iterator that returns a proxy object with it and this is annoying. 因此,我不能使用一个复杂的迭代器来返回一个代理对象,这很烦人。
On the other side, I looked online to other notable implementations and this isn't as common as I thought initially - eg Intel TBB offers its own parallel for each that accepts input iterators. 另一方面,我在网上查看了其他值得注意的实现,这并不像我最初想象的那样常见 - 例如,英特尔TBB为每个接受输入迭代器的提供了自己的并行。

My question is then: why doesn't the parallel std::for_each work with input iterators? 我的问题是:为什么并行std::for_each不能与输入迭代器一起工作?
I cannot see the point of them being forward iterators, because at first glance it should work fine even with input iterators. 我看不出它们是前向迭代器的重点,因为乍一看它即使使用输入迭代器也应该工作正常。 What am I missing? 我错过了什么?

There is a known flaw with the C++17 iterator model in that proxy iterators can only ever be input iterators, for the reasons you point out. 由于你指出的原因,C ++ 17迭代器模型存在一个已知的缺陷,即代理迭代器只能是输入迭代器。 This has lots of downsides. 这有很多缺点。 The parallel algorithms don't need non-proxy iterators, but they definitely need the multi-pass guarantee. 并行算法不需要非代理迭代器,但它们肯定需要多次通过保证。 And the current iterator category model conflates the two. 当前的迭代器类别模型将两者混为一谈。

With C++20 ranges, we get this idea of iterator_concept , which is a backwards-compatible shim to properly support proxy iterators. 对于C ++ 20范围,我们得到了iterator_concept概念,它是一个向后兼容的填充程序,可以正确支持代理迭代器。 You can have an iterator_category of input_iterator_tag but an iterator_concept of forward_iterator_tag , for instance. 例如,您可以使用input_iterator_tagiterator_category ,但可以使用forward_iterator_tagiterator_concept The new ForwardIterator concept does not look at the category, it looks at the concept: 新的ForwardIterator概念没有考虑该类别,它着眼于这个概念:

 template<class I> concept ForwardIterator = InputIterator<I> && DerivedFrom<ITER_CONCEPT(I), forward_iterator_tag> && Incrementable<I> && Sentinel<I, I>; 

Whether or not the parallel algorithms will change is a different question that I can't answer. 并行算法是否会改变是一个我无法回答的不同问题。

The C++17 iterator concepts define a forward iterator as being the weakest form of iterator that requires multiple iterators in the same range to function. C ++ 17迭代器概念将前向迭代器定义为最弱的迭代器形式,它需要在相同范围内运行多个迭代器。 That is, you're allowed to copy a forward iterator, increment the copy, but still access the original value through the original iterator. 也就是说,您可以复制前向迭代器,增加副本,但仍然可以通过原始迭代器访问原始值。

The pure IntputIterator concept only requires single-pass. 纯IntputIterator概念只需要单遍。 Once you increment an iterator, all other copies of it become effectively invalid. 一旦递增迭代器,它的所有其他副本实际上都是无效的。

Being able to parallelize for_each ultimately requires each parallel invocation to get a distinct set of iterators and values to operate on. 能够并行化for_each最终需要每次并行调用以获得一组独特的迭代器和值来进行操作。 That means the iterator has to be copyable and independent of the others. 这意味着迭代器必须是可复制的并且独立于其他迭代器。 Which requires them to be forward iterators. 这需要他们成为前向迭代器。

Now yes, that means you can't use proxy iterators with parallel for_each , even if your iterators are independent of each other. 现在是的,这意味着你不能使用并行for_each代理迭代器,即使你的迭代器是相互独立的。 That's just the limitations of the C++17 iterator concept model. 这只是C ++ 17迭代器概念模型的局限性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM