boost :: container :: vector比std :: vector更快吗?为什么?

时间:2013-01-02 19:34:32

标签: c++ boost vector std

我对boost vector和std vector做了一个有趣的测试,如下所示

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发布,由vc2010编译,/ O2 / Oy -

表示N = 10000

for std vector:0.140849s wall,0.140401s user + 0.000000s system = 0.140401s CPU(99.7%)

f boost vector:0.056174s wall,0.062400s user + 0.000000s system = 0.062400s CPU(111.1%)

,N = 100,000

std:14.050757s wall,14.055690s user + 0.000000s system = 14.055690s CPU(100.0%)

提升:5.585048s墙,5.584836s用户+ 0.000000s系统= 5.584836s CPU(100.0%)

向两者添加保留(N)时,CPU时间变化很小。

他们之间有什么区别? Boost比std快得多,为什么?感谢。

检查sizeof(),std :: vector 16,同时检查boost :: container :: vector 12.

2 个答案:

答案 0 :(得分:6)

请记住,所有代码的速度因编译器和编译器的版本而异。标准库提供了从平台到平台可移植的代码,但很难做出速度保证。

如果您只在自己的计算机上运行此代码,那么您应该选择更快的选项,如果这是您想要的。如果你问这个问题是因为你想做出一个普遍更快的选择,那么我认为没有办法知道什么是缺乏测试。

当然,当人们想象一般的速度时,就像你看起来那样,你想要评估插入许多不同数量的对象,运行许多重复测试,并使用各种对象(类,双打,角色等等。您也可以选择使用不同数量的可用堆栈空间来完成所有这些操作。如果你不考虑所有因素,那么你的问题默认为“为什么,在我的特殊情况下,是否存在速度差异?”通常很难说。

一个更好的问题可能是,“我已经在各种测试条件下观察到这两个类似功能代码之间的速度差异。它们之间是否存在一些可能导致这种情况的架构差异?”答案可能是。

cplusplus.com on std::vector

  

在内部,向量使用动态分配的数组来存储它们   元素。可能需要重新分配此数组才能增长   插入新元素时的大小,这意味着分配一个新元素   数组并将所有元素移动到它。这是相对昂贵的   在处理时间方面的任务,因此,矢量不重新分配   每次将一个元素添加到容器中。

     

相反,矢量容器可以分配一些额外的存储空间   适应可能的增长,因此容器可能有一个   实际容量大于严格需要包含的存储容量   它的元素(即它的大小)。图书馆可以实现不同的   增长战略,以平衡内存使用和   重新分配,但无论如何,重新分配只应发生在   对数增长的间隔大小使插入   可以提供向量末尾的各个元素   摊销的常数时间复杂度(见push_back)。

由此我们看到您所看到的行为取决于您正在使用的STL库的特定版本,并且该增长应该是对数的,并且这种增长通常需要大量复制。 deque不需要大量复制,因此在测试中可能会更好地扩展。

据推测,boost::container的功能相似。我不知道,因为我找不到它的记录。但我找到了this

  

Boost.Container提供的所有容器都实现了放置   插入,这意味着对象可以直接构建到   来自用户参数的容器,不创建任何临时对象。   对于没有可变参数模板的编译器,支持放置插入   被模拟到有限(10)个参数。

如果std :: vector不使用类似的体系结构而是创建临时对象,则可能导致运行时间的差异。但这可能不适用于int类型。也许其他人可以找到不同的架构差异。

答案 1 :(得分:0)

boost :: container中的容器类大量使用扩展的分配器,这些分配器不仅允许分配和解除分配,构造和解构,而且还尽可能扩展分配的内存块。在许多情况下,这意味着更少的复制,并且实质上在c ++方面可以实现与c:中相同的功能:

char * data;
char * newdata = malloc(newdatasize);
memcpy(newdata,data,datasize);
swap(data,newdata);
free(newdata);

https://www.boost.org/doc/libs/1_68_0/doc/html/container/extended_allocators.html 插入int时,所有“放置插入”优化都不重要,因为int的构造很简单。