none
批次影像處理(單一可處理,批次會記憶體不足) RRS feed

  • 問題

  • 批次影像處理(單一可處理,批次會記憶體不足)

    要計算多張50~90MB TIF 的PSNR
    一次單張時,可以得出結果但一次批次下去做時
    可能前一張(或前二張)會有結果,可時之後就會記憶體不足了

    我有想過要優化程式碼
    可是不知如何下手...

    PS:圖--右鍵在開新視窗,可看大圖
    • 已編輯 mkdh 2013年1月4日 上午 04:07
    2013年1月4日 上午 04:05

解答

  • 試著在 GC.Collect 之後用 Thread.Sleep 讓執行緒停一下,  看看能不能改善.

    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    • 已標示為解答 mkdh 2013年1月4日 上午 08:46
    2013年1月4日 上午 06:47
    版主

所有回覆

  • 如果是記憶體不足就要換64位元的系統, 並加裝記憶體, 只改程式的做法也只能一張一張地做
    2013年1月4日 上午 04:23
  • 您好,

    是否每處理完一張後,就先把Resource放掉,再處理下一張!

    如果還有問題的話,您可以使用「ANTS Memory Profiler」看看能不能找出原因!


    以上說明若有錯誤請指教,謝謝。
    亂馬客blog: http://www.dotblogs.com.tw/rainmaker/

    2013年1月4日 上午 04:41
  • 我能做的只有改程式...
    2013年1月4日 上午 05:03
  • 嗯~有空我會試試看...(ANTS Memory Profiler 7.4)。

    在我沒加GC.collect時,有時可以跑二千多張(每張約35MB)。但有時只能跑十幾張或個位數

    我有用工作管理員觀察過程式執行時記憶體的變化。

    所以想說:可不可以一張做完就把Resource放掉?

    所以我加了GC.collect。雖然效率真的變的比較慢了,但至少比較穩定。(<35MB的TIF)

    我的CODE現在在58MB~90MB時,批次是不行的(如附圖)。單張可以。

    所以是不是我GC.collect要加在其他的地方?明顯寫不好的地方?還是建議我要改那裡?


    2013年1月4日 上午 05:18
  • 試著在 GC.Collect 之後用 Thread.Sleep 讓執行緒停一下,  看看能不能改善.

    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    • 已標示為解答 mkdh 2013年1月4日 上午 08:46
    2013年1月4日 上午 06:47
    版主
  • 您好,
    msdn上有GC的相關資訊,給您參考一下。
    記憶體回收告知

    以上說明若有錯誤請指教,謝謝。
    亂馬客blog: http://www.dotblogs.com.tw/rainmaker/

    2013年1月4日 上午 07:20
  • 感恩,眼睙都快流到手背上了~

    我加了System.Threading.Thread.Sleep(1);後,先試3張60MB TIF->OK
    30張60MB TIF->OK

    只是加了...
    方案一.GC.collect和System.Threading.Thread.Sleep(1);
    30張/20分

    方案二.GC.collect
    159張/HR

    方案三.都不加
    177張/HR

    現在我已用方案一,在試跑60MB的 120張。
    六日用方案二跑<40MB的。
    • 已標示為解答 mkdh 2013年1月4日 上午 07:48
    • 已取消標示為解答 mkdh 2013年1月4日 上午 08:46
    2013年1月4日 上午 07:47
  • 感恩,眼睙都快流到手背上了~

    我加了System.Threading.Thread.Sleep(1);後,先試3張60MB TIF->OK
    30張60MB TIF->OK

    只是加了...
    方案一.GC.collect和System.Threading.Thread.Sleep(1);
    30張/20分

    方案二.GC.collect
    159張/HR

    方案三.都不加
    177張/HR

    現在我已用方案一,在試跑60MB的 120張。
    六日用方案二跑<40MB的。

    Hi 您好,

    看了一下您的Code,其實改幾個地方就能快很多。

    1)改用指標的方式讀取資料,不要用GetPixel,可以Google一下LockBits

    2)執接在ImageForm裡計算,不需要再取出RGB的副本,這會消耗你很多額外的記憶體。

    以上,參考看看。

    2013年1月7日 上午 08:58
  • 指標和在ImageForm中直接算PSNR。

    嗯,我會試看看。

    謝謝您。

    2013年1月10日 上午 01:10
  • Hi,

    這邊我提出幾點建議,不只針對記憶體不足的問題...

    1. 300 * 1024 * 1024 提出來...固定的值不要每次都算一次
    2. Result改用ListBox...不要為了換行一直去append newline
    3. txtAllPSNR.txt在btnPSNR_Click觸發時看起來是為了清除資料,是否可改成直接刪除檔案?
    4. txtTemp != ""那邊可以改成txtTemp.Lenth>0
    5. GetPixel => LockBits
    6. mse那邊的計算不需要的強制轉型過多
    7. Convert.ToDouble(txtPSNR)可以提出變數
    8. MyImage1 != null是不必要的檢查
    9. MyPSNR內的ALLPSNRTxt若是提出來可避免檔案流開開關關
    10. ImageForm會同時存放兩份在記憶體,一個是建構子建立出來的image,一個是getRGBData內建出來的bimage

    不過記憶體的部分我覺得問題還是在第十點跟記憶體回收這邊

    我覺得ImageForm內的image可能沒有辦法在你呼叫ImageForm.dispose時就被釋放

    因為Form並不知道你這個成員變數是有非推管資源的

    所以ImageForm內的image我覺得應該是透過Image的解構子去回收的

    如果是這樣可能要等到ImageForm被回收

    image的強引用才會消失...

    強引用消失後GC才能回收

    而要解構的物件又會被加到處理解構的處理串列去解構

    所以導致沒辦法說回收就回收

    我的建議是把ImageForm拿掉,這邊我也沒看到你有把這視窗秀出來

    那倒不如把處理邏輯從View抽出,問題也比較好看...


    謙卑學習,持之以恆,才能不斷的Level Up http://www.dotblogs.com.tw/larrynung/


    2013年1月27日 上午 10:37