![](/img/trans.png)
[英]Why is std::vector::operator[] 5 to 10 times faster than std::vector::at()?
[英]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.開始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.