随机插入/删除的综合载体与链表基准

时间:2012-03-19 02:58:30

标签: c++ vector linked-list benchmarking

所以我知道this问题,以及其他关于问题的问题,但其中大部分问题涉及数据结构的复杂性(只是复制到这里,理论上将其与O连接起来(

我理解复杂性似乎表明列表会更好,但我更关注现实世界的表现。

注意:这个问题的灵感来自于slides 45 and 46 of Bjarne Stroustrup's presentation at Going Native 2012,他在这里讨论了处理器缓存和引用的位置如何真正有助于向量,但根本没有(或足够)与列表有关。 / p>

问题:有没有一种很好的方法来测试这个使用CPU时间而不是墙上时间,并获得一个“随机”插入和删除可以事先完成的元素的体面方式,所以它不影响时间?

作为奖励,能够将其应用于两个任意数据结构(例如矢量和哈希映射或类似的东西)以在某些硬件上找到“真实世界性能”将会很棒。

1 个答案:

答案 0 :(得分:5)

我想如果我要测试这样的东西,我可能会从这个顺序的代码开始:

#include <list>
#include <vector>
#include <algorithm>
#include <deque>
#include <time.h>
#include <iostream>
#include <iterator>

static const int size = 30000;

template <class T>
double insert(T &container) {
    srand(1234);
    clock_t start = clock();
    for (int i=0; i<size; ++i) {
        int value = rand();
        T::iterator pos = std::lower_bound(container.begin(), container.end(), value);
        container.insert(pos, value);
    }
// uncomment the following to verify correct insertion (in a small container).
//  std::copy(container.begin(), container.end(), std::ostream_iterator<int>(std::cout, "\t"));
    return double(clock()-start)/CLOCKS_PER_SEC;
}


template <class T>
double del(T &container) {
    srand(1234);
    clock_t start = clock();
    for (int i=0; i<size/2; ++i) {
        int value = rand();
        T::iterator pos = std::lower_bound(container.begin(), container.end(), value);
        container.erase(pos);
    }
    return double(clock()-start)/CLOCKS_PER_SEC;
}       

int main() { 
    std::list<int> l;
    std::vector<int> v;
    std::deque<int> d;

    std::cout << "Insertion time for list: " << insert(l) << "\n";
    std::cout << "Insertion time for vector: " << insert(v) << "\n";
    std::cout << "Insertion time for deque: " << insert(d) << "\n\n";

    std::cout << "Deletion time for list: " << del(l) << '\n';
    std::cout << "Deletion time for vector: " << del(v) << '\n';
    std::cout << "Deletion time for deque: " << del(d) << '\n';

    return 0;
}

由于它使用clock,这应该给处理器时间而不是挂起时间(尽管某些编译器如MS VC ++会出错)。它不会尝试测量插入时间,不包括查找插入点的时间,因为1)需要更多的工作,2)我仍然无法弄清楚它会完成什么。它肯定 100%严格,但鉴于我从中看到的差异,我会有点惊讶地发现与更仔细的测试有显着差异。例如,使用MS VC ++,我得到:

Insertion time for list: 6.598
Insertion time for vector: 1.377
Insertion time for deque: 1.484

Deletion time for list: 6.348
Deletion time for vector: 0.114
Deletion time for deque: 0.82

使用gcc我得到:

Insertion time for list: 5.272
Insertion time for vector: 0.125
Insertion time for deque: 0.125

Deletion time for list: 4.259
Deletion time for vector: 0.109
Deletion time for deque: 0.109

将搜索时间考虑在内并不是一件容易的事,因为你必须分别对每次迭代计时。您需要比clock(通常是)更精确的东西来从中产生有意义的结果(更多关于顺序或读取时钟周期寄存器)。如果你认为合适的话,请随意修改 - 正如我上面提到的,我缺乏动力,因为我看不出这是一件明智的事情。