【发布时间】:2015-04-30 07:01:41
【问题描述】:
我遇到了以下问题。我有一个平均每秒运行 60 帧的游戏。每一帧我都需要将值存储在一个容器中,并且不能有重复项。
它可能每帧必须存储少于 100 个项目,但插入调用的数量会更多(并且由于它必须是唯一的而许多被拒绝)。只有在帧的末尾我才需要遍历容器。因此,每帧大约有 60 次容器迭代,但插入次数更多。
记住要存储的项目是简单的整数。
我可以使用很多容器,但我无法决定选择什么。性能是其中的关键问题。
我收集的一些优点/缺点:
矢量
- (PRO):连续内存,一个巨大的因素。
- (PRO):可以先保留内存,之后很少分配/释放
- (CON):除了遍历容器 (std::find) 每个 insert() 来查找唯一键之外,别无选择?比较很简单(整数),整个容器可能适合缓存
设置
- (专业版):简单,明确的目的
- (CON):插入时间不固定
- (CON):每帧有很多分配/解除分配
- (CON):非连续内存。遍历一组数百个对象意味着在内存中跳来跳去。
unordered_set
- (专业版):简单,明确的目的
- (PRO):平均大小写常数时间插入
- (CON):鉴于我存储整数,散列操作可能比其他任何操作都贵很多
- (CON):每帧有很多分配/解除分配
- (CON):非连续内存。遍历一组数百个对象意味着在内存中跳来跳去。
由于内存访问模式,我倾向于使用向量路由,即使 set 显然是针对这个问题的。我不清楚的一个大问题是遍历每个插入的向量是否比分配/释放(特别是考虑到必须执行的频率)和 set 的内存查找成本更高。
我知道最终这一切都归结为对每个案例进行剖析,但如果只是作为先发制人或只是理论上,那么在这种情况下什么可能是最好的?是否还有我可能遗漏的优点/缺点?
编辑:正如我没有提到的,容器在每一帧结束时被清除()
【问题讨论】:
-
只需测量即可。 鉴于
unordered_set是 经典的“集合”容器,无序- 重复语义和最佳渐近复杂度,我会试一试,但vector很有可能会在小型容器中击败它,因为它具有更好的缓存位置属性。 -
如何提供自己的分配器,以克服内存管理效率低下的问题? (例如提供对象池)
-
无论你做什么,试着正确地封装你的代码并使用
auto来跟踪类型,这样你以后就可以轻松地改变你对容器的选择。然后测量。 -
如果您知道向量中要存储的值的范围,您可以将它们放在自己的向量中,然后在容器上使用random_suffle,并从中获取前 100 个元素。
-
A
set可能会受到分支错误预测的支配。完整的数据适合 L1 并且可以避免分配(块分配器)。但是,set是一个树形结构,因此每个插入的错误预测概率约为 50% 的多个分支是不可避免的。
标签: c++ memory-management containers