met*_*fox 7 c++ iterator stl-algorithm c++17
我有一个可以简化为基本的并行代码:
#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);
}
Run Code Online (Sandbox Code Playgroud)
我想通过使用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]);
});
}
Run Code Online (Sandbox Code Playgroud)
这可行,但是更加冗长,更糟糕的是,我认为它不符合标准,因为它boost::counting_iterator
是一个存储迭代器,因此不符合Cpp17ForwardIterator的要求.
是否可以像OpenMP一样简洁地编写上述代码,同时满足并行算法标准的约束条件?
如果我的算法正确,我们必须
KeyObjPtrVec
向量,Key
结构体的字段匹配,我们必须调用Calculate
结构Obj
体的字段。C++17 具有出色的内置并行化支持,这可以通过标准库轻松完成:
#include <algorithm>
#include <execution>
void Calculate(std::vector<TKeyObjPtr> const &KeyObjPtrVec) {
std::vector<size_t> indices(KeyObjPtrVec.size());
for (size_t k = 0; k < indices.size(); k++) {
indices[k] = k;
}
std::for_each(std::execution::par, indices.begin(), indices.end(),
[KeyObjPtrVec, indices](size_t k) {
std::for_each(std::execution::par, indices.begin() + k + 1, indices.end(),
[k, KeyObjPtrVec](size_t l) {
if (KeyObjPtrVec[k].Key == KeyObjPtrVec[l].Key) {
KeyObjPtrVec[k].ObjPtr->Calculate(KeyObjPtrVec[l]);
}
});
});
}
Run Code Online (Sandbox Code Playgroud)
如果您指定std::execution::par
为 的第一个参数std::for_each
,则并行版本运行。无需关心执行程序、线程同步或任何清理 - 所有这些都可以开箱即用。只需链接库tbb
(target_link_libraries(myexecutable tbb)
用于 cmake)。
使用std::for_each您可以访问您应该处理的元素,而不是迭代器。为了获得设置第二个所需的更多自由访问权限std::for_each
,我们创建索引数组并对其进行迭代。有了元素的索引,我们就可以在两个 lambda 中的任何相对位置访问数组。
该代码经过测试并确认可以按照答案开头所述工作。
归档时间: |
|
查看次数: |
208 次 |
最近记录: |