c++ - 用 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);
}
我想通过使用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要求。
是否可以像使用 OpenMP 一样简洁地编写上述代码,同时满足标准对并行算法的约束?
解决方案
迭代器可以按值赋值。分配的迭代器是一个副本,当原始分配源增加时不会前进。因此,您可以简单地
template<typename I>
void calculate(const I It1, const I It2) {
// This statement can also run at any time later. The iterators will point
// how they were when the calculate(...) was called.
It1->ObjPtr->Calculate(*It2);
}
void Calculate(std::vector<TKeyObjPtr> const &KeyObjPtrVec) {
for (auto It1 = KeyObjPtrVec.begin(); It1 != KeyObjPtrVec.end(); ++It1)
for (auto It2 = It1 + 1; It2 != KeyObjPtrVec.end() &&
It2->Key == It1->Key; ++It2)
calculate(It1, It2);
}
不幸的是,C++17 并不是一个专用的并行编程平台。您需要安排一个有意义大小的线程池和任务队列,他们可以从中挑选任务。任务记录可以只保存分配为结构字段的这两个迭代器。您还需要一种机制来了解所有并行处理何时完成,以便您可以继续。
推荐阅读
- python - Python中for循环中的列堆栈矩阵
- c# - 如何在源生成器中查找类声明的文件路径
- python - Python Selenium 没有名称、没有 id、没有文本、许多类和 aria-label 的单击按钮
- javascript - React 组件仅处理数据(无渲染组件)
- python - 智能聊天机器人没有从数据中学习
- python - 给定一个整数数组,从 1 到 X 找到总和为 N 的 K 个数字
- uuid - 在转换现有的唯一 ID 集时,UUID V5 是否提供了合理的唯一性假设?
- powerbi - powerBI中的OLAP在哪里
- php - PHP根据数组计数将数字动态拆分为小数部分
- node.js - 错误:不受支持的状态或无法验证数据