簡體   English   中英

std :: vector &lt;std :: vector <unsigned char> &gt;或std :: deque &lt;std :: vector <unsigned char> &gt;?

[英]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上復制的請求對嗎?


更新:
1)據DeadMG稱, MSVC9進行了這種類型的優化(Swaptimization- TR1已在VC9 SP1中修復 )。 gcc 4.3可能不會進行這種優化。

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.

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