簡體   English   中英

std :: deque比std :: vector更快插入到最后?

[英]Is std::deque faster than std::vector for inserting at the end?

我開始比較:

  • 插入列表的前面
  • 插入向量的背面
  • 插入一個雙端隊列的前面

但后來我注意到即使在push_back() ,deque似乎也更快了。 我一定做錯了什么 ,我不敢相信一個更普通的容器會勝過某個特定容器。

我使用谷歌基准測試的代碼:

#include "benchmark/benchmark.h"
#include <deque>
#include <vector>

#define NUM_INS 1000

static void BM_InsertVector(benchmark::State& state) {
    std::vector<int> v;
    v.reserve(NUM_INS);
    while (state.KeepRunning()) {
        state.PauseTiming();
        v.clear();
        state.ResumeTiming();
        for (size_t i = 0; i < NUM_INS; i++)
            v.push_back(i);
    }
}
BENCHMARK(BM_InsertVector);

static void BM_InsertDeque(benchmark::State& state) {
    std::deque<int> v;
    while (state.KeepRunning()) {
        state.PauseTiming();
        v.clear();
        state.ResumeTiming();
        for (size_t i = 0; i < NUM_INS; i++)
            v.push_back(i);
    }
}
BENCHMARK(BM_InsertDeque);

BENCHMARK_MAIN();

結果:

Run on (1 X 2592 MHz CPU )
2016-02-18 14:03:47
Benchmark         Time(ns)    CPU(ns) Iterations
------------------------------------------------
BM_InsertVector       2820       2470     312500                                 
BM_InsertDeque        1872       1563     406977

在使用元素數量時,我注意到一些差異,但是deque總是優於矢量。

編輯:編譯器: gcc version 5.2.1編譯: g++ -O3 -std=c++11 push_front.cpp -lbenchmark -lpthread

我認為-O3實際上是工具性的; 當我關閉它時,我的deque性能會稍差一些

我認為向量較慢,因為你正在調用clear() ,這取決於你的STL實現,可能會釋放底層數組存儲。

如果是這種情況,那么你的reserve()電話沒有幫助; 並且您的矢量不斷調整大小,這需要將每個元素移動到新的更大的存儲空間。

連續向動態容器添加元素涉及基本上3個成本來源:

  1. 內存管理。
  2. 容器的內部簿記。
  3. 需要對元素本身執行的任何操作。 值得注意的是, 任何使插入時引用無效的容器都可能會移動/復制元素。

讓我們從1.開始vector繼續要求內存加倍,並且deque分配固定大小的塊( deque通常實現為數組陣列,較低層數組具有固定大小)。 要求更多的內存可能需要更長的時間,但通常要求更少,但通常情況下,除非你的堆非常分散,一次性要求一個大塊是獲得一些內存的最快方法。 分配一個meg一次可能更快,然后要求千字節1000次。 所以很明顯, vector最終會在這里具有優勢(直到容器如此之大,它受到碎片的影響)。 然而,這最終不是:你只要求1000個元素。 我寫了以下代碼http://coliru.stacked-crooked.com/a/418b18ff8a81c1c0 它不是很有趣,但它基本上使用一個簡單的分配器來增加全局,以查看執行了多少分配。

在你的基准測試過程中, vector要求內存11次,而deque只有deque一直要求相同數量, vector要求加倍量。 同樣, vector必須free調用10次。 並且deque 0.這似乎是deque的小勝利。

對於內部簿記, vector的實現比deque更簡單。 畢竟, vector只是一個動態數組, deque是一個數組數組,嚴格來說更復雜。 所以這顯然是vector的勝利。

最后,關於操作本身的元素。 deque ,沒有任何東西被移動。 使用vector ,每個新的堆分配也涉及移動所有元素。 它可能被優化為使用memcpy來處理普通類型,但是甚至可以看到,這是對memcpy的10次調用來復制1,2,4,8 ... 512個整數。 這顯然是deque的勝利。

我可以推測,啟動O3可以非常積極地插入deque許多更復雜的代碼路徑,減輕2的重量。但顯然,除非你做更詳細(非常小心!)的基准測試,否則你永遠不會知道肯定。

大多數情況下,這篇文章表明它比簡單的專業容器更復雜,而不是更普遍的容器。 我會做一個預測(把我的脖子剪掉,就像它一樣):如果你增加元素的數量甚至可以說是2或4的因子,你就不會再看到deque win了。 這是因為deque將使堆分配的數量增加2倍或4倍,但是vector只會增加1-2倍。

我在這里deque注意, deque實際上是一種奇怪的數據結構; 它理論上是一個數組數組,但在許多實現中,數組要么是一定的大小,要么只是一個元素,無論哪個更大。 此外,它的一些大O保證是無稽之談。 push_back只是固定的常量時間,因為在C ++中,只對元素本身的操作計入大O.否則應該清楚,因為它是一個數組數組,頂級數組的大小與數量成正比已存儲的元素。 最終,頂級陣列的空間不足,你必須重新分配它,移動O(N)指針。 所以它不是真的O(1) push_back

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM