我对boost向量和std向量做了一个有趣的测试,如下所示
int N = 10000;
{
boost::timer::auto_cpu_timer t;
std::vector<int> v;
for (int i = 0; i < N; ++i)
{
v.insert(v.begin(), i);
}
}
{
boost::timer::auto_cpu_timer t;
boost::container::vector<int> v;
for (int i = 0; i < N; ++i)
{
v.insert(v.begin(), i);
}
}
win32版本,由vc 2010编译,/O2 /Oy-
对于N = 10000
对于标准品载体:0.140849秒墙壁,0.140401秒用户+0.000000秒系统= 0.140401秒CPU(99.7%)
f升压矢量:0.056174秒墙壁、0.062400秒用户+0.000000秒系统= 0.062400秒CPU(111.1%)
对于N = 100,000
标准配置:14.050757秒墙壁,14.055690秒用户+0.000000秒系统= 14.055690秒CPU(100.0%)
提升:5.585048秒墙壁,5.584836秒用户+0.000000秒系统= 5.584836秒CPU(100.0%)
当两者都加上reserve(N)时,CPU时间变化很小。
它们之间有什么区别吗?Boost比STD快得多,为什么?谢谢。
检查std::向量16的大小,同时检查boost::容器::向量12。
2条答案
按热度按时间qlckcl4x1#
请记住,所有代码的速度会因编译器和编译器版本的不同而不同。标准库提供了可移植地在不同平台上工作的代码,但很难保证速度。
如果你只是在自己的机器上运行这段代码,那么你应该选择更快的选项,如果这是你想要的。如果你问这个问题是因为你想做出一个普遍更快的选择,那么我不认为有一种方法可以知道这是什么短的测试。
当然,当人们对速度感到疑惑时,就像您看起来那样,您可能希望通过插入许多不同数量的对象、运行许多重复测试和使用各种对象来评估速度(classes,double,chars,等等)。你也可以选择使用不同的可用堆栈空间来完成所有这些操作。如果你没有考虑所有的因素,那么你的问题默认为,“为什么,在我的特殊情况下,有速度差异?”这通常很难说。
一个更好的问题可能是:“我观察到在各种测试条件下,这两段功能相似的代码之间存在速度差异。它们之间是否存在某种架构差异,可以解释这种差异?”答案是可能。
cplusplus.com on std::vector
在内部,向量使用一个动态分配的数组来存储它们的元素。当插入新元素时,这个数组可能需要重新分配以增加大小,这意味着分配一个新数组并将所有元素移动到它。就处理时间而言,这是一个相对昂贵的任务,因此,向量不会在每次向容器添加元素时重新分配。
相反,向量容器可以分配一些额外的存储空间以适应可能的增长,并且因此容器可以具有比包含其元素严格需要的存储空间更大的实际容量库可以实现不同的增长策略以平衡存储器使用和重新分配,但是在任何情况下,重新分配应当仅以对数增长的大小间隔发生,使得在向量末尾插入各个元素可以具有分摊的恒定时间复杂度(参见push_back)。
从这里我们可以看出,你所看到的行为取决于你所使用的STL库的特定版本,增长应该是对数的,增长通常需要大量的复制。deque不需要大量的复制,所以它在你的测试中可以更好地扩展。
大概
boost::container
的功能也是类似的,我不知道,因为我找不到关于它的文章,但我找到了this:Boost提供的所有容器都实现了放置插入,这意味着对象可以直接从用户参数构建到容器中,而无需创建任何临时对象。对于没有可变模板支持的编译器,放置插入最多模拟为有限(10)个参数。
如果std::vector没有使用类似的架构,而是创建了一个临时对象,这可能会导致运行时的差异。但这可能不适用于
int
类型。也许其他人可以找到不同的架构差异。tkclm6bt2#
boost::container中的container类大量使用了扩展的分配器,这些分配器不仅允许分配和解除分配、构造和解构,而且还可以扩展已分配的内存块,这意味着在许多情况下减少了复制,并且本质上是在执行c++中的c
realloc
:https://www.boost.org/doc/libs/1_68_0/doc/html/container/extended_allocators.html
当插入int时,没有一个“位置插入”优化是相关的,因为int是平凡构造的(意味着在这种情况下,接受的答案不是正确的解释)。