[英]std::vector< std::vector<unsigned char> > or std::deque< std::vector<unsigned char> >?
我有一個現有的算法,如果可能的話,我需要適當地對其進行優化。 目前無法在此算法中進行大量更改。 該算法適用於std::vector< std::vector<unsigned char> >
實例。 看起來像這樣:
typedef std::vector<unsigned char> internal_vector_t;
std::vector< internal_vector_t > internal_vectors;
while (fetching lots of records) {
internal_vector_t tmp;
// reads 1Mb of chars in tmp...
internal_vectors.push_back(tmp);
// some more work
}
// use this internal_vectors
該算法使用push_back()在internal_vectors
實例中插入了很多次。 internal_vector_t的大多數實例的大小為1 Mb 。 由於internal_vectors
的大小是未知的,因此不會事先完成reserve()。
我不明白的第一件事是當internal_vectors
達到其當前容量時,需要分配一個新塊並將其當前內容復制到更大的內存塊中,這是怎么回事。 由於大多數塊的大小為1Mb,因此復制操作很長。 我是否應該期望編譯器(gcc 4.3,MS VC ++ 2008)將設法對其進行優化以避免復制 ?
如果復制不可避免,將更改為std::deque
help嗎? 我考慮使用std :: deque,因為我仍然需要按諸如internal_vectors [10]之類的索引進行訪問。 像這樣:
typedef std::vector<unsigned char> internal_vector_t;
std::deque< internal_vector_t > internal_vectors;
// the same while
據我了解std::deque
不需要重新分配曾經分配的位置。 我在這種情況下的std::deque
是否會要求較少的分配和在push_backs上復制的請求對嗎?
2)我已經介紹了使用std::deque< std::vector<unsigned char> >
的算法版本,我發現它的性能更好。
3)我還利用了Mark Ransom建議的使用swap
。 使用此功能可以改善性能:
internal_vector_t tmp; internal_vectors.push_back(empty); tmp.swap(internal_vectors.back());
MSVC9的標准容器實現了一種稱為“ swaptimization”的功能。 它是移動語義的較弱版本。 調整外部向量的大小時,它將不會復制內部向量。
但是,您最好只是簡單地將編譯器升級到MSVC10或GCC(我認為是4.5),這將為您提供移動語義,這將大大提高此類操作的效率。 當然, std::deque
可能仍然是更聰明的容器,但是move語義在許多地方對性能都有好處。
每次將internal_vector_t
插入internal_vectors
,它都會復制一個internal_vector_t
。 無論您使用vector
還是deque
都是如此。 標准容器始終會復制您要插入的對象。
您可以通過插入一個空的internal_vector_t
消除復制,然后將插入的對象的內容與您真正想要插入的對象swap
。
有時,向量在插入過程中空間不足時需要調整自身大小,這將導致對象再次被復制。 只要您始終插入開頭或結尾,雙端隊列將消除這種情況。
編輯:我上面給出的建議可以通過這些代碼更改進行總結。 此代碼應避免所有復制大向量。
typedef std::vector<unsigned char> internal_vector_t;
std::deque< internal_vector_t > internal_vectors;
internal_vector_t empty;
while (fetching lots of records) {
internal_vector_t tmp;
// reads 1Mb of chars in tmp...
internal_vectors.push_back(empty);
tmp.swap(internal_vectors.back());
// some more work
}
std::deque
不會連續存儲其元素-它將其存儲分解為一系列恆定大小的“塊”。 這意味着,當std::deque
容量不足時,它僅需要分配一個恆定大小的新塊-無需重新分配其整個內部緩沖區並移動其所有現有元素。
另一方面, std::vector
確實會保持連續存儲,因此當容量用完並重新分配時,確實需要移動所有現有元素-這可能會很昂貴。
std::vector
關於它的重新分配方案是“智能的”,根據幾何級數(通常是將容量增加一倍或增加1.5等)按塊分配。 這意味着重新分配不會經常發生。
在這種情況下, std::deque
可能會更有效,因為當重新分配確實發生時,它的工作量就會減少。 與往常一樣,您必須進行基准測試才能獲得任何實數。
您的代碼可能會在其他方面得到進一步改進。 似乎在while
循環的每次迭代中,您都在創建一個新的internal_vector_t tmp
。 在循環外聲明它可能更有效,而::clear()
其存儲在每次迭代中。 每次調用internal_vectors.push_back(tmp)
時,您也要復制整個tmp
矢量-您可以通過通過internal_vectors.push_back(std::move(tmp))
移動tmp
矢量來改善這一點。一些指針。
希望這可以幫助。
您正在索引外部向量嗎? 如果不是,那么std::list<std::vector<unsigned char> >
怎么樣?
取決於實現,出隊可能更有效。 與向量不同,出隊將無法保證連續存儲,因此可以分配幾個單獨的內存塊。 因此,它可以分配更多內存,而無需移動元素。 您應該嘗試一下並評估影響。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.