在C++中,在不损失速度的情况下提高元组映射的内存消耗

Improve memory consumption of a map of tuples without losing speed in C++

本文关键字:元组 映射 内存 C++ 损失 情况下 速度 高元组      更新时间:2023-10-16

为了存储5元组的成本,我有一个映射如下:

std::map<std::tr1::tuple<u32, u32, u32, u32, u8>, f32> costsMap_;

在运行时,有几个这样的表要加载到内存中,每个表大约有2.5*10⁷条目。每个条目都有表格

2.16345 # 5875 396 # 47512 26445 # 2

并且使用CCD_ 1从盘中读取。之后,条目保持不变。

许多元组的差异仅在于1个值,即有许多值出现在相当多的条目中。我想利用这个事实,不要经常存储不必要的值。

我试过一系列像这样的地图

std::map<u32, std::map<u32, std::map<u32, std::map<u32, std::map<u8,f32>>>>> costsMap_;

但这太慢了,因为在短短几分钟内就有数百万次查找,因此查找也必须相当快(它还没有完全优化到运行时)。

有没有一种方法可以将表加载到内存中,从而使内存消耗显著下降(至少下降2倍),同时在运行时不会损失太多速度?

您可以通过按最常见前缀的长度拆分元组来减少重叠,而不是在每个级别进行拆分。

例如,假设您的数据在元组的前三个成员上有大量重叠,即,如果您只考虑映射中每个元组的前3个成员,则不同条目的数量会下降几个数量级。在这种情况下,您可以将地图拆分为多个地图。我还建议使用unordered_map,因为它是渐进的更快。

std::unordered_map<std::tr1::tuple<u32,u32,u32>,std::unordered_map<std::tr1::tuple<u32,u8>,f32> > costsMap_;

这种方法以额外查找为代价,减少了密钥存储的重复。只有当存储的元组的前缀之间的重复数量足够高,足以证明额外的查找是合理的时,它才能节省开支。

注意,这种方法是你在帖子中建议的地图扩展方法的推广,前三个和后两个位置"融合"成元组。你可以选择其他点进行分割——例如,如果前四个键经常重复,你可以使用

std::unordered_map<std::tr1::tuple<u32,u32,u32,u32>,std::unordered_map<u8,f32> > costsMap_;

除了最后一个查找键之外的所有查找键都"融合"到一个元组中。