如C++般飛奔的C#

來源:互聯網
上載者:User

用C#實現一個映像邊緣檢測演算法,處理一個300*375的圖片竟然用了2.38s,吐血。用VSTS的程式碼分析工具發現,GDI+裡面的GetPixel()這個函數竟然佔用了已耗用時間的53.92%而SetPixel()佔用了7.14%,光是映像的讀入和輸出就佔了60%+(見圖1)。這樣的速度可受不了。稍微分析一下就能得出原因,Bitmap是一個通用類,可以用來處理多種映像格式,因此GetPixe()l和SetPixel()的效率自然會在諸多分支跳轉中受到拖累,再加上這兩個函數被頻繁反覆調用,對程式效率的影響尤為明顯。再深入想一想,實際上這樣的函數無非是把一塊記憶體複製並返回而已,因此可以考慮直接深入Bitmap的內部用指標糟吊搞,這樣不僅可以省去反覆調用函數壓棧彈棧記憶體配置等瑣碎工作,也能夠在映像格式已經確定下來的前提下節約分支跳轉的時間。


圖1 VSTS中對代碼啟動並執行採樣分析結果

放狗搜了一下,Google大神告訴我們,其實微軟已經考慮到了這樣的效率問題,提供了兩個東西,一個叫做BitmapData類,專門給需要效率的同學實現上面的思路,一個是傳說中的Unsafe Code支援,使得C#中仍然可以使用指標,為BitmapData的使用創造了條件。至於細節上如何使用這個類,執行緒安全性,記憶體如何對齊等問題,詳詢10086,此處不述。或者也可以拜讀這位同學的文章:使用C#進行影像處理的幾種方法。(此文贊一個,寫得相當清楚)
採用這種方案對實現進行改進後,對同一張圖片的處理時間變為了0.19s,時間縮短了92%,這還是可以接受的。當然,進一步的改進仍然需要,這就是另一個問題了。

由此可見,當效率不理想的時候,不要怨天尤人,不要怪C#或Java此類語言先天不足。而應該先用工具搞清楚問題究竟出在什麼地方,然後抓主要矛盾,著重最佳化這幾個函數。此外,有的放狗也是重要技巧之一。一開始用關鍵字"GDI+ 效率 C#",搜出來一堆關於"GDI+比OpenGL效率還高"的資料,後來換了"GetPixel C# 效率",就搜出了相關文章。此外在沒有網路的時候也可以去看看MSDN,事實上如果認真閱讀MSDN中Bitmap.Members這個文檔的話,會發現LockBits()這個函數,深入探究下去也可以找到相當詳細的資料和常式。總而言之,積極的態度,理性的分析和工具的合理利用是克服困難的有力武器。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.