【发布时间】:2016-01-11 22:52:39
【问题描述】:
我有一个巨大的数组(例如,ParticleId[]),由 唯一 个整数(代表粒子 ID)组成,它们以随机顺序存储在内存中。我需要构建一个哈希表来将每个 ID 映射到它在数组中的位置,即从 ID 到索引。 ID 不一定是连续整数,因此简单的查找数组不是一个好的解决方案。
我目前正在使用 c++11 的 unordered_map 容器来实现这一点。使用循环初始化地图:
unordered_map <ParticleId_t, ParticleIndex_t> ParticleHash;
ParticleHash.rehash(NumberOfParticles);
ParticleHash.reserve(NumberOfParticles);
for(ParticleIndex_t i=0;i<NumberOfParticles;i++)
ParticleHash[ParticleId[i]]=i;
ParticleId_t 和 ParticleIndex_t 只是类型定义的整数。
NumberOfParticles 可以很大(例如,1e9)。就哈希表而言,ParticleId[] 数组和NumberOfParticles 是const。
目前,如上所述构建unordered_map 需要花费大量时间。我的问题是:
-
unordered_map是这个问题的最佳选择吗?-
map的初始化速度是否会更快,尽管它在查找时可能效率不高?
-
- 是否可以加快初始化速度?
- 使用
ParticleHash.insert()是否比使用ParticleHash[]=快得多?或任何其他功能? - 鉴于我的键是唯一整数,有没有办法优化映射以及插入?
- 使用
我正在考虑使用英特尔concurrent_unordered_map 来并行化它。但是,这会引入对英特尔 TBB 库的依赖,如果可能的话,我想避免这种情况。有没有使用原生 STL 容器的简单解决方案?
更新:
现在我已经恢复到一个普通的排序索引表并依靠bsearch 进行查找。至少表的初始化现在快了 20 倍,并且可以轻松并行化。
【问题讨论】:
-
看看这个——包括关于在构造函数中指定桶大小的评论:stackoverflow.com/questions/11614106/…
-
使用
std::map你可以传递一个提示迭代器来加速插入。如果您知道下一个键是地图中的最后一个键,则可以传递 end 迭代器作为我相信的提示。我不知道这是否会比无序地图更快。还要考虑 boost 提供的一些 flat_map 数据结构。 -
@JerryJeremiah:啊,我使用的是 gcc4.7.2。也许这就是原因。在确认之前我必须找到另一个编译器..
-
@NeilKirk:地图中的最后一个是指最后插入的还是有序键中的最后一个?如果是后者,我认为我最好选择自己的实现,先排序,然后是 binary_search
-
从 gcc4.7.2 切换到 4.8.1 的速度提高了 2 倍。Turing 优化 -O3 的速度提高了 2 倍。
标签: c++ performance hashmap unordered-map scientific-computing