2010-06-24 104 views
5

黑族社區,刪除指針的時間

我對刪除指針有個小問題。

我正在使用Dimension 1024x1024指針指針矩陣。由於我是動態創建它們的,因此我在程序結束時刪除了爲它們分配的空間。但是在通常的循環中這樣做會花費很多時間 - 我使用處理器的時鐘速率測量了大約2秒。如果程序運行時間僅爲15秒,則2秒鐘的時間會很長 - 使用這些分配的指針的函數被調用的時間不止一次。

下面是代碼所測量的時間關鍵片包括測量:

time=clock(); 
for(i=0;i<xSize;i++){   //xSize is dynamic, but 1024 for the measurement 
    delete [] inDaten[i]; 
    delete [] inDaten2[i]; 
    delete [] copy[i]; 
} 
delete inDaten; delete inDaten2; delete copy; 
time=clock()-time; 
    time/=CLOCKS_PER_SEC; 

總是長正在刪除指針?或者我只是做錯了事情?

我希望這裏有人能幫我解決這個問題。由於我正在優化一個相當複雜的程序以加快運行速度,所以我無法使用這些2秒的代碼。與所有其他部分相比,這只是太慢了。但是我仍然需要能夠動態地實現這個代碼。 SmartPointers可能會有幫助,但如果我理解正確,他們也需要時間來刪除自己 - 只是在不同的時間...

感謝您的答案!

Baradrist

編輯:我剛剛發現,即測量這些刪除的計算的速度很慢,因爲我沒有在釋放模式編譯。由於調試器發揮作用,我測量了這些(最終虛幻)數字,這讓我很頭疼。最終的程序會自動進行自動優化,以便幾乎不再有時間參與刪除操作。

反正:感謝所有有用的答案!他們給了我很多額外的知識和想法!

+1

「inDaten」,「inDaten2」和「copy」中的對象的類型是什麼?它們只是整數或類似的東西,還是它們是真實的物體? – 2010-06-24 12:01:33

+1

你需要動態分配一切嗎?你需要這麼多的*單獨的*分配嗎?是否有可能重寫程序來存儲更少,更大的分配數據? – jalf 2010-06-24 12:06:12

+0

在我的上網本上,刪除double []並沒有達到下一個時鐘週期,所以無論是用附加的調試器運行,還是在陣列中元素的析構函數中發生了一些昂貴的事情。 – 2010-06-24 12:06:34

回答

3

delete[]也會爲數組的每個元素調用析構函數,這會增加時間,除非析構函數是微不足道的。

除此之外 - 是的,動態內存分配相對昂貴。如果你無法容忍它 - 試着分配更少的更大塊,或者不要在時間關鍵的東西中進行動態分配。

智能指針不會有太大幫助 - 它們會在內部執行相同的釋放操作。它們不是爲了加速,而是爲了方便設計。

1

如果您在程序結束時刪除它們,並且運行析構函數並不重要,則只需省略刪除 - 操作系統將取消分配內存。否則,嘗試使用單個間接指針,即不要使用指針指針數組。除了減少刪除時間,這也會改善參考的地點。

+2

無法保證操作系統將釋放任何內存。 – Yacoby 2010-06-24 11:55:42

+3

@Yacoby:除非操作系統本身給出這樣的保證。任何現代(桌面)操作系統都可以。 – jalf 2010-06-24 12:05:50

+0

無論操作系統是否清理出口處的進程內存,依靠這樣的柺杖仍然是不好的做法。最好使用更適合快速釋放的分配器,和/或重新設計代碼以儘量減少釋放(當然,不會引入泄漏)。 – Void 2010-06-24 23:10:55

2

這裏有一個有趣的線程「Memory Allocation/Deallocation Bottleneck?

分配和釋放需要很長的時間,因此是你擁有的最常見的昂貴的操作之一。這是因爲堆管理必須處理一堆事情。在調試模式下,通常也會在內存塊上進行更多的檢查。如果你在發佈配置中有相同的時間,我會感到驚訝,通常至少有兩個因素在起作用。有了私有堆,你可以大大增加事物。如果你總是分配相同大小的對象,那麼內存池可能是最好的選擇。

0

嘗試創建自己的內存分配方法,以便減少銷燬時間。

例如從Os請求一塊內存並將其分配給它,以便您可以將整個塊釋放到一個操作系統中。

1

看起來問題出在你的數據結構中。爲什麼你需要這麼多的動態分配?可以做些什麼來減少分配數量?

如果釋放指針需要2秒鐘,它可能至少需要分配它們。

只要退出程序,就可以避免釋放它們。 C++並不保證所分配的內存會發生什麼,但是你的操作系統可能會這樣做,所以在實際的條款中,它可能是一個簡單的方法來削減2秒的執行時間。

但是,這仍然留下> 2秒的分配。

我認爲,最好的辦法是嘗試更好地構建數據。你能向我們展示矩陣當前的結構嗎?

+0

使用1-dim矩陣節省時間!你對結構是正確的。矩陣包含pinys的灰度(如1024x1024等)。 但仍然:分配是比解除分配方式更快(測量明智) – Baradrist 2010-06-24 12:35:56

0

非常感謝所有快速答案!很高興看到有人在那裏幫助=)。仍然爲我的問題,似乎我必須處理這種時間的損失,因爲我需要動態數組作爲臨時矩陣在較小的子程序中,最終不會執行。

反正:再次謝謝!祝你有愉快的一天!

Baradrist

+0

使用一維矩陣應該做的伎倆 - 謝謝! – Baradrist 2010-06-24 12:28:47

0

如果對象指出,在你的陣列有不平凡的析構函數沒有太多可以做,以提高顯著運行時不解決,第一。否則:

而不是使指針的大小isizeinDaten, inDaten2 and copy陣列尺寸isize數組爲什麼不能讓他們大小isize*isize的陣列和,而不是解決與個別項目:array[i][j]array[i*isize+j]解決這些問題。 這樣你就可以打電話給delete []

1

不應該是這樣:

delete [] inDaten; delete [] inDaten2; delete [] copy; 

因爲使用的,他們顯然陣列。 (至少他們看起來也是,你沒有提供足夠的上下文)。

+0

是的,它應該是 - 已經改變它,但它不會改變時間數字=)。 – Baradrist 2010-06-24 12:18:58

0

對此的優化是以區塊形式分配內存,分配帶有新位置的單個指針並在刪除時刪除整個區塊。

但是,您必須小心謹慎,因爲此選項隱含地暗示不會調用每個分配了新位置的對象的析構函數。

1

你不會說數組中的對象有多大,但是如果它們足夠大,有可能部分內存被換出並需要被換回(或者可能只是重新映射回進程空間),這就是你所看到的時間。

0

如果您確定內存分配/釋放是瓶頸並希望速度更快,那麼第一個明顯的解決方案是使用陣列的連續緩衝區。你仍然可以提供一個矩陣接口來訪問它們,就像二維數組一樣。

// Rudimentary Implementation 
template <class T> 
class SquareMatrix 
{ 
public: 
    explicit SquareMatrix(int i_size): 
     size(i_size), mat(new T[i_size * i_size]) {} 

    ~SquareMatrix() 
    { 
     delete[] mat; 
    } 

    // could also be column depending on row-major/col-major 
    T* operator[](unsigned int row) 
    { 
     return mat + row * size; 
    } 

    // could also be column depending on row-major/col-major 
    const T* operator[](unsigned int row) const 
    { 
     return mat + row * size; 
    } 

private: 
    unsigned int size; 
    T* mat; 
}; 

第二個明顯的事情是,而不是三個矩陣,有一個矩陣是由具有你所需要的數據的構成。這是假設一個元組矩陣就足夠了,這似乎是你發佈的代碼的情況。

如果你真的想去核心,並需要多個矩陣,然後編寫你自己的內存分配器。您可以一次爲多個矩陣分配內存,並使用新的放置位置來構造它們。如果你想這樣做,需要進一步的閱讀和學習,因爲編寫內存分配器不是一件小事:你需要考慮像對齊這樣的問題,但這是最快的方法。

我建議您仍然抓取分析器而不是依賴時序測試,並對代碼進行適當的調用圖分析。這會告訴你究竟花了多少時間在哪裏。例如,可能是因爲矩陣中物體的建造/毀壞並不像它可能的那樣便宜。

缺乏顯而易見的算法效率低下,即使是非常有知識的程序員也往往對其代碼中的瓶頸不正確。如果效率是一個主要問題,那麼剖析器就是您最好的朋友。

0

如果矩陣中指針所引用的所有對象都是相同類型(或至少大小相同),則可以分配一大塊內存來保存它們並將它們初始化到原位。