一个整数散列问题

An integer hashing problem

本文关键字:问题 整数 一个      更新时间:2023-10-16

我有一个(c++) std::map<int, MyObject*>,它包含几百万个类型为MyObject*的对象。我能拥有的对象的最大数量,大约是1亿个。键是对象的id。在某个过程中,这些对象必须以某种方式尽快标记(用01)。标记不能发生在对象本身上(所以我不能引入成员变量并将其用于标记过程)。因为我知道最小和最大id(1到100_000_000),所以我想到的第一个想法是使用std::bit_set<100000000>并在那里执行标记。这解决了我的问题,也使标记进程并行运行时更容易,因为这些使用自己的bit_set来标记事物,但我想知道解决方案是什么,如果我必须使用其他东西而不是0 - 1标记,例如,如果我必须用整数标记所有对象,我可以使用什么?

是否有某种形式的数据结构可以以紧凑(内存方面)的方式处理这类问题,并且速度很快?我们感兴趣的主要查询是对象是否被标记,以及标记了什么。

谢谢。

备注:std::map<int, MyObject*>不可修改。无论我使用什么数据结构,都不能处理映射本身

把地图的value_type改成std::pair<bool, MyObject*>而不是MyObject*怎么样?

如果您不关心内存,那么std::vector<int>(或任何适合您需要的int)应该可以工作。

如果你不喜欢这样,你不能修改你的地图,那么为什么不为标记创建一个平行的地图呢?

std::map<id,T> my_object_map;
std::map<id,int> my_marker_map;

<年代>如果不能直接修改对象,是否考虑过在将对象放入映射之前对其进行包装?例如:

struct
{
    int marker;
    T *p_x;
} T_wrapper;

std::map<int,T_wrapper> my_map;

如果你无论如何都需要做查找,那么这不会变慢。

EDIT:正如@tenfour在他/她的回答中建议的那样,std::pair可能是一个更干净的解决方案,因为它保存了struct定义。就我个人而言,我不是std::pair s的忠实粉丝,因为你必须将所有内容都称为firstsecond,而不是有意义的名称。但那只是我…

要问自己的最重要的问题是"这1亿个对象中有多少可能被标记(或保持未标记)?"如果答案大约小于100,000,000/(2*sizeof(int)),那么只需使用另一个std::setstd::tr1::unordered_set (hash_set之前的tr1)来跟踪哪些是如此标记(或保持未标记)。

2*sizeof(int)从何而来?它是对在一组将要被标记的项列表中维护堆结构所需的内存开销的估计。

如果它更大,那么使用您即将使用的std::bitset。对于你所需要的数量来说,它的管理费用实际上是0%。你需要大约13mb的连续内存来保存bitset。

如果您需要存储标记和存在,则使用std::tr1::unordered_map使用Object*的键和marker_type的值。同样,如果标记节点的百分比高于上述比较,那么您将需要使用某种bitset来保持所需的位数,并适当调整大小,为12.5兆字节/位。

考虑到需求的澄清,持有bitset的专用对象可能是您的最佳选择。


Edit:这假设您已经对您可以接受的解决方案进行了适当的时间复杂度计算,因为不再允许更改基本std::map结构。

如果您不介意使用hack,请查看Boost.MultiIndex中使用的内存优化。它可以在存储指针的LSB中存储一位