8

技術堆棧:C#/。NET 4 /的WinForms策略需要處理大量的圖像數據的工作

背景:

上我的工作是一系列圖像棧的可視化應用項目。具體而言,每個圖像堆棧都與網格對齊,每次顯示相同的圖像,並將處理功能應用於當前可見的圖像。圖像堆棧本身爲150-300 MB,每個圖像爲512KB-1MB。一個典型的數據集將包含〜100個圖像堆棧。

問:

試着和這個數據量的工作,我用幾個technqiues:

  • 內存映射文件:圖像堆棧從磁盤在應用程序啓動
  • 彙編下加載帶有不安全代碼的x64:顯然,我需要64位地址空間來存放這種大小的文件。我將當前顯示的圖像從內存映射文件移動到一個方法,該方法通過Marshal.Copy生成位圖並使用不安全的指針。
  • System.Threading.Tasks:我使用的並行循環,處理在可能的情況
  • System.Drawing.BufferedGraphicsContext:每個圖像堆棧具有被傳遞給一個PictureBox用於顯示給之前合成到一個BufferedGraphicsContext一個活動圖像用戶。
  • 高端系統要求:四核以上CPU,SSD,12GB內存等

然而,即使使用所有上述情況,reponsiveness極不理想。使用SysInternals Process Explorer時,CPU利用率很低(< 25%),而內存使用率在垃圾回收發生之前爬升到限制。

分析表明大部分執行時間都是從內存映射文件中獲取數據。我認爲它正在等待操作系統將請求的內存返回到活動內存中?

我還能做些什麼來提高性能?

注:

  • 大多數,如果不是全部,圖像棧將在同一時間,以便裁剪到當前視口可能不會產生太大的速度可見。
  • 調整大小以顯示是一個選項,但完整的原始數據必須始終可用於處理,因此它似乎只是一個額外的步驟。

更新1:

  • 內存,我的開發只有6 GB(我嘗試加載較少的文件作爲一個結果),但部署系統將有24 GB 。
  • 我正在研究通過英特爾性能基元和通過CUDA的GPU加速優化SSE。
  • 我試圖將所有數據加載到內存中的原因是因爲重要的可視化步驟是以15-60 Hz循環圖像堆棧,並且我害怕抖動。
+0

只是想檢查等價 - 有沒有辦法有很多,這可能只是交給圖形卡而煩惱? – 2012-02-01 21:53:08

+0

「大量的記憶」是給你什麼? – 2012-02-01 21:53:53

回答

5

首先,我認爲使用不安全的代碼和內存映射文件不是很有幫助。您需要從磁盤讀取大約20GB的數據。如果你只是使用流 - 你在錯誤的地方進行了優化,那麼從磁盤讀取它會比內存中的一個額外副本花費更多的時間。

我想你應該看它從一個不同的角度。您可以在顯示器上顯示少於10MB數據的圖像堆棧 - 價值20GB。您無需讀取20GB數據即可顯示所有圖像堆棧,並在處理這些圖像時提供響應式用戶界面。你只需要從每個堆棧中加載頂部圖像 - 這將更快地得到很多

至於實際的處理,除非你能夠以某種方式利用GPU,否則我認爲你可以比並行處理圖像更快。我想這取決於你實際做的處理。

0

正如聽起來那樣,你應該嘗試在應用程序啓動時觸摸(即從每個文件的開頭讀取4KB的每個倍數的一個字節)存儲器映射文件中的所有數據。既然你有足夠的內存,問題可能不是操作系統將你的映像分頁,而是最初不會分頁。內存映射文件被延遲加載,所以操作系統在你真正嘗試訪問內存映射文件中的數據。因此,在應用程序加載時觸摸內存將導致磁盤讀取發生,而不是用戶正在查看圖像堆棧的時間。

0

減少並行處理的圖像的數目來增加存儲器局部性。 因此,你的4個核心應該同時處理一個圖像。 這對處理器緩存很有用。

2

您仍然可以爲每張圖像預先生成拇指圖像,並在所有圖像都可用時僅加載Grid。在用戶將圖像應用效果/轉換的時刻,您可以僅加載該圖像。即使期間該圖像的加載,您可以在devide裝貨裁剪部門和異步的方式加載它們。如果你看看Google Street View,它是如何加載,縮放後了,你會弄清楚,從未整個圖像(即使它是由你的要求)立即加載,但它通過行業加載。

另一個非常有趣的技術我認爲,Deep Zoom可以,如果不是你的問題的答案,但至少可以提供一個很好的提示。

Another example on Deep Zoom斯科特Hanselman的

好運。

0

根據圖像有多大的顯示器,並且,你可以嘗試下采樣的圖片以適應方形堆棧。然後,如果你想專注於圖像的一些點的分辨率,則可以重新加載原始圖像。

如果您使用的是WPF,則可以嘗試使用DecodePixelWidth和DecodePixelHeight。也許存在的WinForms