[心得] 比較陣列的相減後取絕對值速度

看板C_Sharp作者 (源)時間14年前 (2010/01/15 23:19), 編輯推噓1(109)
留言10則, 4人參與, 最新討論串1/2 (看更多)
這份文章起因是因為目前遇到影像處理的小問題,CCD可以每秒抓6張(2452*2054*16), 但是自己寫的影像處理的時間需要280ms,也就是每秒只能處理3.5張影像,跟不上影像進 來的速度。第一種解決方案是使用市面上的影像處理軟體(ex. Matlab, LabView Vison, OpenCV),第二種是想辦法改進演算法。在經過方案一的交叉測試後後,我開始著手方案 二。 這邊簡單的說明一下我所使用的CCD運作模式,ActiveX元件將影像放入CCD宣告的顯示 記憶體,這時可呼叫ActiveX方法將影像複製一份到我所想要的記憶體,可以是一維,也 可以是二維,但是陣列內的元素數量相同。我想要達成的目標是即時的影像相減(第n張與 第1張相減取絕對值然後以PictureBox顯示),為了簡化問題,本次文章直接以亂數產生陣 列代表取入的影像,並將重點放在加快陣列相減後取絕對值的速度。 我所使用的硬體為C2D E6550 2.34G*2 RAM 3.25G,,30次測試平均值如下: Visual Studio 2008 C# 的測試結果 兩組一維陣列(1,2452*2054)相減取絕對值,所需時間為52.604ms 兩組二維陣列(2452,2054)相減取絕對值,所需時間為278.125ms Matlab2009b 的測試結果 兩組一維陣列(1,2452*2054)相減取絕對值,所需時間為42.819ms 兩組二維陣列(2452,2054)相減取絕對值,所需時間為41.405ms NI Measurement Studio 8.6 的測試結果(使用axCWArray元件) 兩組一維陣列(1,2452*2054)相減取絕對值,所需時間為559.375ms 兩組二維陣列(2452,2054)相減取絕對值,所需時間為1443.75ms Maltlab影像處理測試結果 imabsdiff所需時間為86.724ms (兩張相減後取絕對值) imsubstract所需時間為17.726ms (兩張影像相減) Visual Studio 2008 C# 將一維陣列轉成影像輸出給PictureBox所需時間為31.250ms 小結論: 1. 在C#中使用一維陣列做影像處理能夠大幅度的減少運算時間。 2. 兩組一維陣列相減後取絕對值,轉成影像輸出給PictureBox總共需要時間83.854ms ,小贏Matlab(86.724ms) XDD。 3. 若要再加快處理速度,需要考慮多執行緒與組合語言搭配使用。 小問題: 1. 承小結論3,請版上強者大大能夠指點我的程式碼,提供改進的建議,謝謝。 附上我的程式碼 // 比較相同element數量的一維陣列與二維陣列相減時間 // 一維陣列相減52.08ms 、二維陣列相減285.9375ms // 同迴圈內頭尾同時計算對時間沒有影響 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace myImageSub { public partial class mainForm : Form { public mainForm() { InitializeComponent(); ushort[] myArray1 = new ushort[2452 * 2054]; ushort[] myArray2 = new ushort[2452 * 2054]; ushort[] myArray3 = new ushort[2452 * 2054]; ushort[,] myArray4 = new ushort[2452, 2054]; ushort[,] myArray5 = new ushort[2452, 2054]; ushort[,] myArray6 = new ushort[2452, 2054]; Random myRnd = new Random(); double tempTime01, tempTime02; TimeSpan clock01 = new TimeSpan(); int cycleTimes = 5; // 一維陣列計算速度 for (int i = 0; i < cycleTimes; i++) { for (int j = 0; j < myArray1.Length; j++) { myArray1[j] = (ushort)myRnd.NextDouble(); myArray2[j] = (ushort)myRnd.NextDouble(); } System.DateTime startTime = DateTime.Now; for (int j = 0; j < myArray1.Length; j++) { myArray3[j] = (ushort)Math.Abs(myArray1[j] - myArray2[j]); } clock01 = (DateTime.Now - startTime) + clock01; } tempTime01 = (clock01.TotalMilliseconds / cycleTimes); // 二維陣列計算速度 for (int i = 0; i < cycleTimes; i++) { for (int j = 0; j < myArray4.GetLength(1); j++) { for (int k = 0; k < myArray4.GetLength(0); k++) { myArray4[k, j] = (ushort)myRnd.NextDouble(); myArray5[k, j] = (ushort)myRnd.NextDouble(); } } System.DateTime startTime = DateTime.Now; for (int j = 0; j < myArray4.GetLength(1); j++) { for (int k = 0; k < myArray4.GetLength(0); k++) { myArray6[k, j] = (ushort)Math.Abs(myArray4[k, j] - myArray5[k, j]); } } clock01 = (DateTime.Now - startTime) + clock01; } tempTime02 = (clock01.TotalMilliseconds / cycleTimes); MessageBox.Show("一維陣列相減所需時間為" + tempTime01.ToString() + " ms \r\n" + "二維陣列相減所需時間為" + tempTime02.ToString() + " ms"); } } } -- -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.112.46.87

01/16 11:29, , 1F
你寫得很好,不過這種結論似乎不用經過你驗證,稍有程度的
01/16 11:29, 1F

01/16 11:29, , 2F
人早就知道了.
01/16 11:29, 2F

01/16 11:30, , 3F
如果你把上面的程式加上組語版本的比較發表到ASM板,我會
01/16 11:30, 3F

01/16 11:31, , 4F
給個"推"!
01/16 11:31, 4F

01/16 13:55, , 5F
一維比二維快是應該的,因為少了array到記憶體的加法
01/16 13:55, 5F

01/16 13:55, , 6F
要比應該要用unsafe mode用pointer
01/16 13:55, 6F

01/17 20:13, , 7F
為什麼會比Matlab之流的還慢?該不會在debug mode吧?
01/17 20:13, 7F

01/18 14:33, , 8F
推要用unsafe mode的指標來跑
01/18 14:33, 8F

01/18 14:34, , 9F
Matlab矩陣運算是強項 慢是慢在他是直譯式的執行
01/18 14:34, 9F

01/18 14:36, , 10F
要快還可以用顯卡加速 關鍵字:CUDA 或 GPU Programming
01/18 14:36, 10F
文章代碼(AID): #1BK8UGH5 (C_Sharp)
文章代碼(AID): #1BK8UGH5 (C_Sharp)