我有一个大字符串列表存储在一个巨大的内存块中(通常有100k +甚至1M +)。这些实际上是哈希值,因此字符串的字母表限制为A-F0-9,每个字符串的长度恰好为32个字节(因此它存储为“压缩”)。我将从现在开始将此列表称为主列表。
我希望能够从主列表删除项目。这通常是以批量方式完成的,所以我得到一个大的列表(通常大约100到10k)哈希,我需要在这个列表中找到并删除它们。在此操作结束时,大内存块中不能有任何空块,因此我需要考虑到这一点。不保证所有项目都在主列表中,但不会有多次。无法重新定位,主要块将始终保持相同的大小。
通过主列表迭代并检查是否已删除给定哈希的天真方法当然有效,但有点慢。此外,小内存块的移动有点过多,因为每次将哈希标记为删除时,我都会使用主列表的最后一个元素重写它,从而满足无空块的条件。这当然会创建成千上万的小memcpy ,这反过来会减慢因为我得到大量的缓存未命中。
有更好的方法吗?
一些重要的注释:
答案 0 :(得分:2)
好的,如果我绝对不得不优化地狱,那么这就是我要做的事情。 我假设订单无关紧要,因为您(IIUC)通过将项目与最后一项交换来删除项目似乎就是这种情况。
dict
使用的最初切断的越来越多的比特。现在,与使用现成的解决方案相比,这会带来更多的工作和维护负担。我不会建议它,除非它真的像你的描述中那样对性能至关重要。
如果C ++ 11是一个选项,并且编译器的unordered_set
是好的,也许你应该只使用它并节省大部分麻烦(但要注意这可能会增加内存需求)。您仍然需要专门化std::hash
和std::equal_to
或operator==
。替代为Hash
提供您自己的KeyEqual
和unordered_set
,但这可能不会带来任何好处。
答案 1 :(得分:1)
两件事可能有所帮助。首先,至少对项目列表进行排序
即将被删除;这样,您就可以使用二进制搜索
(std::lower_bounds
)就可以了。第二,保持两个指针:
来源和目的地。如果源指向某事
不在要删除的列表中,将其复制到目标,然后
推进两者。如果源指向要删除的内容,
只需前进源指针,无需复制。应该
永远不会成为不止一次复制条目的理由。