如何在CPU和内存中优化C 中的重型地图插入
How to optimize heavy map insertion in C++ regarding CPU and memory
我迭代了一张地图,我需要在该地图上添加元素,这取决于找不到元素的条件(可能是其他任何条件)。
我的主要问题是,要添加大量更新,应用程序会采用整个CPU和所有内存。
状态类:
class State {
int id;
int timeStamp;
int state;
}
状态中的方法:
void State::updateStateIfTimeStampIsHigher(const State& state) {
if (this->id == state.getId() && state.getTimeStamp() > this->getTimeStamp()) {
this->timeStamp = state.getTimeStamp();
this->state = state.getState();
}
}
循环代码:
std::map<int, State> data;
const std::map<int, State>& update;
for (auto const& updatePos : update) {
if (updatePos.first != this->toNodeId) {
std::map<int, State>::iterator message = data.find(updatePos.first);
if (message != data.end() && message->first) {
message->second.updateStateIfTimeStampIsHigher(updatePos.second);
} else {
data.insert(std::make_pair(updatePos.first, updatePos.second));
}
}
}
观看kcachegrind数据,看起来像 data.insert()行需要大部分时间/内存。我是Kcachegrind的新手,但是这条线似乎是费用的72%。
您对如何改善这一点有任何建议吗?
您的问题是相当一般的,但是我看到要使它运行得更快的东西:
- 使用提示的插入/安置。当您添加新元素时,其迭代器将返回。假设这两个地图都是以相同的方式订购的,您可以说出最后一个地图在哪里,因此查找应该更快(可以在此处使用一些基准测试)。
- 使用
emplace_hint
进行更快的插入
示例代码在这里:
std::map<int, long> data;
const std::map<int, long> update;
auto recent = data.begin();
for (auto const& updatePos : update) {
if (updateElemNotFound) {
recent = data.emplace_hint(recent, updatePos);
}
}
另外,如果要通过内存交易CPU,则可以使用unordered_map(在琐碎键的情况下使用地图而不是unordered_map有任何优势吗?),但是第一个点不再重要了。
我可以找到一个令人满意的答案,这要归功于该问题的评论。从 map 更改为 unordered_map ,但我仍然有不令人满意的结果。
我最终使用了Google的Sparsehash,尽管擦除条目有一些缺点(我愿意)。
。代码解决方案如下。首先,我包括所需的库:
#include <sparsehash/sparse_hash_map>
然后,我的新数据定义看起来像:
struct eqint {
bool operator()(int i1, int i2) const {
return i1 == i2;
}
};
google::sparse_hash_map<int, State, std::tr1::hash<int>, eqint> data;
由于我必须使用"擦除",因此我必须在 sparsemap 构造之后这样做:
data.clear_deleted_key();
data.set_deleted_key(-1);
最后,我的循环代码更改很少:
for (auto const& updatePos : update) {
if (updatePos.first != this->toNodeId) {
google::sparse_hash_map<int, State, std::tr1::hash<int>, eqint>::iterator msgIt = data.find(updatePos.first);
if (msgIt != data.end() && msgIt->first) {
msgIt->second.updateStateIfTimeStampIsHigher(updatePos.second);
} else {
data[updatePos.first] = updatePos.second;
}
}
}
时间在特定参数下进行整个应用程序进行更改为:
real 0m28,592s
user 0m27,912s
sys 0m0,676s
和时间在按照相同的特定参数进行整个应用程序进行更改是:
real 0m37,464s
user 0m37,032s
sys 0m0,428s
我将其与其他情况以及相似的结果(从定性的角度来看)。系统时间和资源使用率(CPU和内存)减少,用户时间增加。
总的来说,我对这一权衡感到满意,因为我更关心资源使用而不是执行时间(应用程序是模拟器,它无法完成并在真正的重负载下获得结果,现在确实如此)。
相关文章:
- 为什么不;名字在地图上是按顺序排列的吗
- 基于多个条件处理地图中的所有元素
- 在C++中将矢量转换为嵌套地图
- 替换基于地图的所有引用
- 如何区分地图中的 0 和 false?
- 地图计数确实很重要,或者只是检查是否存在
- 如何从地图中删除矢量对象
- 是否有任何C++功能可以对地图进行排序?
- 如何使用 std::variant 打印地图键/值?
- 从矢量或地图中删除共享指针
- 在 c++ 中,有一种方法可以创建一个包含地图作为值的树状地图?
- 无限嵌套具有变体的地图
- C++一会儿循环读到地图上 2 行?
- 如何在cpp中使用地图显示给定日期范围内(在下面的问题中)的费率?
- 如何检查变量是否是C++中的地图?
- 如何使地图按值C++排序
- 修改地图内矢量中的值
- 为什么我在地图中搜索STL时差很大?
- 我正在尝试按降序对地图进行排序,但没有得到预期的结果?
- 如何在CPU和内存中优化C 中的重型地图插入