【发布时间】:2019-06-28 12:59:57
【问题描述】:
我有一个并行代码,基本上可以简化为:
#include <algorithm>
#include <vector>
struct TKeyObjPtr;
class TObj
{
public:
virtual void Calculate(TKeyObjPtr const &) = 0;
};
struct TKeyObjPtr
{
int Key;
TObj *ObjPtr;
};
void Calculate(std::vector<TKeyObjPtr> const &KeyObjPtrVec)
{
#pragma omp parallel for
for (auto It1= KeyObjPtrVec.begin(); It1!=KeyObjPtrVec.end(); ++It1)
for (auto It2= It1+1; It2!=KeyObjPtrVec.end() && It2->Key==It1->Key; ++It2)
It1->ObjPtr->Calculate(*It2);
}
我想通过使用c++17 并行算法对代码进行现代化改造。 不幸的是,我在重写这么简单的一段代码时遇到了麻烦。
一个选项是使用boost::counting_iterator:
void Calculate(std::vector<TKeyObjPtr> const &KeyObjPtrVec)
{
std::for_each(std::execution::par_unseq,
boost::counting_iterator<std::size_t>(0u),
boost::counting_iterator<std::size_t>(KeyObjPtrVec.size()),
[&KeyObjPtrVec](auto i)
{
for (auto j= i+1; j<KeyObjPtrVec.size() && KeyObjPtrVec[j].Key==KeyObjPtrVec[i].Key; ++j)
KeyObjPtrVec[i].ObjPtr->Calculate(KeyObjPtrVec[j]);
});
}
这可行,但更冗长,更糟糕的是,我认为它不符合
标准,因为 boost::counting_iterator 是一个存储迭代器,因此不
见Cpp17ForwardIterator requirements。
是否可以像使用 OpenMP 一样简洁地编写上述代码,同时满足 标准对并行算法的限制?
【问题讨论】:
-
你确定
counting_iterator不是ForwardIterator 吗? Afaik ForwardIterator 只是使for_each工作所需的最低要求,而不是更多 -
@user463035818 问题是 ForwardIterator 需要返回对某个对象的引用。
counting_iterator按值返回。 -
@metalfox 这不是我在您链接的文档中看到的。我看到
referencetypedef 是const Incrementable&,而operator*确实返回reference -
我不认为这个循环符合“简单”的条件。
It1->ObjPtr->Calculate(*It2);中的迭代器配对源于比较相等的连续Key值,但仅在It1尚未通过的容器部分中,加上迭代器后面的对象配对将多次使用超过两个相等连续键。 -
@user463035818 eel.is/c++draft/forward.iterators#1.3
标签: c++17 c++ iterator c++17 stl-algorithm