Max*_*xpm 4 c++ performance memory-management vector push-back
假设我必须迭代一个可能非常大的数字向量,并将偶数和奇数元素复制到新的单独向量中.(源向量可以有任何比例的均衡;它可以是所有均匀,所有可能性,或介于两者之间.)
为简单起见,push_back通常用于此类事情:
for (std::size_t Index; Index < Source.size(); Index++)
{
if (Source[Index] % 2) Odds.push_back(Source[Index]);
else Evens.push_back(Source[Index]);
}
Run Code Online (Sandbox Code Playgroud)
但是,我担心如果它被用作类似排序算法的实现的一部分,这将是低效的并且是有害的,其中性能是最重要的.例如,QuickSort涉及像这样分离元素.
您可以使用reserve()先前分配内存,因此只需要一次分配,但是您必须迭代整个源向量两次 - 一次计算需要整理的元素数量,再次进行实际复制.
当然,你可以分配与源向量大小相同的空间量,因为新的向量都不需要保留更多,但这似乎有些浪费.
有没有更好的方法让我失踪?是push_back()平时信任来管理这样的事情对于程序员,或者它可以为敏感的算法成为负担?
我将回答我认为你真正要问的问题,"应该push_back()避免在重算法的内循环中?" 而不是其他人似乎已经阅读了你的帖子,这是"如果我在对大型向量进行无关排序之前调用push_back,这是否重要?" 此外,我将回答我的经验,而不是花时间追查引文和同行评审的文章.
你的榜样,基本上是做两件事情,加起来的总CPU成本:它的阅读和输入向量元素操作,然后它插入元素融入到输出向量.您担心插入元素的成本是因为:
malloc()只是慢,即使当学生假装new是不同的东西)你的本能,因此,正确的是:你永远载体预先预留空间如果可能的话,不是因为的push_back是缓慢的,但因为它可以触发一个重新分配这是缓慢的.另外,如果你看一下它的实现shrink_to_fit,你会发现它也会进行复制重新分配,暂时使你的内存成本加倍并导致进一步的碎片化.
这里的问题是你并不总是确切知道输出向量需要多少空间; 通常的反应是使用启发式和自定义分配器.默认情况下,为每个输出向量保留n/2 + k的输入大小,其中k是某个安全范围.这样你通常会有足够的空间用于输出,只要你的输入是合理平衡的,并且push_back可以在极少数情况下重新分配.如果你发现push_back的指数行为浪费了太多的内存(当你真正只需要n + 2时你就会保留2n个元素),你可以给它一个自定义的分配器,以较小的线性块扩展矢量大小 - 当然如果向量真的不平衡并且你最终做了很多调整大小,这将会慢得多.
如果不提前行走输入元件,就无法始终保留足够的空间; 但是如果您知道平衡通常是什么样的,那么您可以使用启发式方法对其进行很好的猜测,以获得多次迭代的统计性能提升.
| 归档时间: |
|
| 查看次数: |
3278 次 |
| 最近记录: |