2012-11-14 121 views
1

今天,我遇到了訪問向量元素隨矢量大小變慢的問題。由於這不是我的代碼,我無法發佈,所以請耐心等待。我會盡可能詳細地描述它。訪問std ::向量元素減慢向量大小

代碼的功能如下: 1. a數據集類,需要一個.txt文件,其中包含文件名。這些指向標準的PNG圖像,需要加載。這由Image<T>類完成。圖像被加載爲Image<unsigned char>並被推回到std::Vector。 2.數據加載完成後。我可以訪問我的數據集中的矢量以便使用它。所以它看起來是這樣的:

Dataset d; 
d.init("filenames_list.txt"); //Loads the images 
for(int i=0; i< d.getDatavector().size(); i++){ 
    Image<unsigned char> current = d.getDatavector()[i]; 
    //Do work on current image here. 
} 

這裏getDatavector()將返回一個std::Vector<Image<unsigned char> >。這些圖像包含三個整數,寬度,高度和通道數量,還有一個指向交錯數據的Boost共享指針。

對於小型testruns,我有一個包含大約150個圖像的文件列表。運行這個程序能正常工作和速度測量告訴我,

Image<unsigned char> current = d.getDatavector()[i];

約需10毫秒內完成。但是,如果我想在我的完整數據集上處理1500張圖像,上面的行需要大約500ms才能完成。我試圖做很多不同的事情來解決它,但是我受到代碼的一般結構和內存的限制。因爲如果我做到以下幾點:

const std::Vector<Image<unsigned char> > data = d.getDatavector();

循環之前

,它的運行速度非常快,但我很快就用完了內存。

我知道我的問題描述有些模糊,我不希望得到確切的解決方案,但我希望提供一些關於在哪裏尋找的提示。我搜索了類似的問題,但人們似乎只關心向量與數組的一般速度。我的問題是,速度隨着矢量的長度而降低!如果有人看到了這種問題,歡迎任何建議!

到目前爲止,我嘗試使用std :: vector :: iterator或使用(d.getDatavector()。data())作爲指針訪問內容。似乎沒有什麼能夠提高速度。

+0

1)你在哪裏開始/停止計時器? 2)你是否想要包含內存分配時間? 3)你是在IDE中還是在IDE(命令行)之外運行它? – 2012-11-14 21:56:56

+2

'getDatavector'是否返回一個引用?或價值? –

+0

確實,這看起來很奇怪,Image數據類型非常小,並且唯一的大部分是由智能指針攜帶的。 – didierc

回答

5

什麼的getDataVector()樣子的簽名?難道

std::vector<Image<unsigned char>> getDataVector(); 

如果是這樣,該函數返回你寫d.getDatavector()[i]vector的一份拷貝每次vector的價值,並且,該i元素被複製出來的vector的,然後vector本身銷燬。

如果你可以修改Dataset類變化的功能

std::vector<Image<unsigned char>> const& getDataVector(); 

現在副本不會進行每次函數被調用的時間。

如果您無法修改該類,請在之前將單個副本輸入到循環中,然後使用循環內的局部變量。

這是不可能的,因爲std::vector的底層數據陣列需要是連續的,因此訪問元件是如添加i指針標記的起始地址一樣簡單的問題是,索引的數據數組並取消引用結果。

+0

非常感謝大家的幫助!這實際上解決了我的問題。我選擇接受這個答案,因爲它是最精細的。這實際上將加載時間從15分鐘縮短到了10秒鐘!特別是循環頭文件中額外的d.getDataVector()。size()增加了額外的時間。傳遞一個const引用而不是複製對象是完美的解決方案,我不需要改變任何東西,除了添加const並且不會破壞通用管道:) – Pandoro

2

您是使用C++ 11還是早期的C++?

如果更早的C++ 11和getDataVector返回一個向量,那麼它可能必須被複制。 如果您使用的是C++ 11,那麼它可以被移動到返回變量中,而不是複製

這可能是您的減速源。

訪問矢量的元素是一個常量操作。

+0

+1。我馬上認爲這個問題是關於它的慢點,而不是每個元素的訪問。 – 2012-11-14 22:03:21

+0

但是,如果您移動'vector','Dataset'類將不會留下它的有效副本。這可能是不可取的。 – Praetorian

5

原因是你在循環中按值返回向量。

讓您getDatavector()返回一個std::Vector<Image<unsigned short> >&std::Vector<Image<unsigned short> > const&std::Vector<Image<unsigned short> >

1

如前所述,問題的根源似乎在於getDatavector()返回矢量的完整副本,解決方案將返回引用(或指針)。
您也有一個Image<unsigned char> current = ...類似的問題,其中也正在製作圖像的副本。
一種解決這些問題將是使用作爲直接訪問圖像:

Image<unsigned char>* getImage(int idx) 
{ 
if (idx < _myVector.size()) 
{ 
    return &_myVector[idx].Image; 
} 
return NULL; 
} 

編輯:版本返回參考

Image<unsigned char>& getImage(int idx) 
    { 
    if (idx < _myVector.size()) 
    { 
     return _myVector[idx].Image; 
    } 
    // throw exception here; 
    } 

顯然,如果你必須有這將無法工作每個圖像的副本。