看板 C_Sharp 關於我們 聯絡資訊
https://github.com/erspicu/filter_test 通常要求即時性的vidoe filter應該少會用全C#去實作, 不過一方面是為了好奇.一方面是挑戰C#效能極限.一方面是相容考量, 所以還是嘗試用純C#來擔任模擬器電玩常見的ScaleX HQX XBRz filter處理任務.... 不過除了 ScaleX 外 , HQX跟XBRz 都是移植人家已經寫好的C#改寫方案, 再加上修改減化.重構.效能校調來的.... 很刺激...你會發現改了啥地方,突然FPS竄升起來,或是幾個零零星星的小地方改一改, 效能累積起來就提升不少,目前除了HQ6X (HQ3*HQ2)效能我覺得不太及格外, 其他擔任一般古早機的scaler,以現在普遍的電腦效能來處理大概都算. 目前這幾個filter,xbrz跟hqx都還有不少校能改善空間,對這種議題有興趣的, 可能嘗試修改看看. 大概的心得是,其實cost最高的是任何跟array數據存取的部分, 也就是說效能瓶頸主要是array記憶體這塊,也難怪記憶體硬體還一直在進化中…. 其他什麼 加減乘除 邏輯判斷等等的cost反來相當低… 但若真的太多累贅的code,同樣會拖慢…. 另外method展開,照理說少了stack push pop返回等動作效能會提升, 但若是展開的code太長太多塞起來,效能反來會大下降, 可能跟code 本身 loading的時間有關係. 這種需求下,其實原則就是程式能盡量簡單就簡單些,看起來酷酷很先進的寫法, 能不用就不要去用,不過這種求精簡破壞物件化結構和維護方便性的做法, 除非特殊原因,不然也不建議. -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 60.248.56.181 ※ 文章網址: https://www.ptt.cc/bbs/C_Sharp/M.1450326300.A.BC8.html
fo40225: 要更快就要用unsafe去存取array與bitmap 12/17 22:46
真的有仔細看內文和稍微看一下專案的內容嗎... ※ 編輯: erspicu (61.70.74.143), 12/18/2015 00:18:49
fo40225: 我看了啊 看到都是用SetPixel 這就慢啊 12/18 12:55
HQX SCALE XBRZ這三個filter全都是用array在計算 你看到的GetPixel SetPixel 只是從bmp取出運算範例array 跟把計算好的結果寫入到bmp中 這兩部分完全不在效能評估的時間內 Stopwatch st = new Stopwatch(); st.Restart(); for (int i = 0; i < 2000; i++) { HS_XBRz.ScaleImage3X(array_org, array_3X, org_width, org_height); } st.Stop(); Console.WriteLine("all time : " + st.ElapsedMilliseconds); int fps = (int)((double)2000 / ((double)st.ElapsedMilliseconds / (double)1000)); Console.WriteLine("fps : " + fps + "\r\n"); Bitmap bmp3x = new System.Drawing.Bitmap(org_width * 3, org_height * 3); for (int i = 0; i < org_width * 3; i++) for (int j = 0; j < org_height * 3; j++) bmp3x.SetPixel(i, j, Color.FromArgb((int)(0xff000000 | array_3X[i + j * org_width * 3]))); pictureBox3.Image = bmp3x; 如果你真的對這專案.議題.文章沒興趣,東西真的可以不需要看一半.
fo40225: .net4.6 x64可以用CPU SIMD加速 那些矩陣處理也可以更快 12/18 12:56
fo40225: 如果計算量夠大 用C++AMP寫邏輯給C#用可以比pfor快 12/18 12:59
文章開頭就寫到 "通常要求即時性的vidoe filter應該少會用全C#去實作, 不過一方面是為了好奇.一方面是挑戰C#效能極限.一方面是相容考量," 然後下面推文寫說可以插C++進去....... ※ 編輯: erspicu (118.171.212.174), 12/18/2015 13:52:59
Litfal: 如果是相容考量,C++應該更好一些,不過得看你相容什麼XD 12/18 16:35
恩 相容的定義其實看那種性質的相容
Litfal: 然後filter系的優化,可以用動態產生IL的技巧,把一些不必 12/18 16:36
Litfal: 要的運算直接去掉,例如x1、x0、x-1這種在filter裡面常出 12/18 16:37
Litfal: 現的。直接動態產生IL的方式,我比較推薦Expression Tree 12/18 16:39
Litfal: 自己寫IL code有點辛苦,雖然有時是必要的... 12/18 16:39
IL code不太熟...不過我猜應該跟我之前k java bytecode大同小異 以後再慢慢看看....
fo40225: 文章 專案沒看懂是我的問題 抱歉 12/18 16:43
fo40225: 但我認為在ScaleImage內的操作 展開成那樣 12/18 16:45
fo40225: JIT的優化都沒了 還不如用unsafe + SIMD 可讀會回來一些 12/18 16:46
fo40225: 這樣也還算是在C#內實作吧?畢竟unsafe操作指標也是C#規格 12/18 16:47
fo40225: 如果操作array是瓶頸那就用unsafe去改 12/18 16:49
fo40225: 都用上pfor平行操作多筆資料了 用上SIMD一次操作更多不是 12/18 16:52
fo40225: 用pfor操作還有可能有CPU cache miss問題 12/18 16:57
fo40225: 展開減少stack push pop也可以試試MethodImplOptions 12/18 17:04
fo40225: MethodImplOptions.AggressiveInlining 12/18 17:04
method展開照理說會減少掉 stack的 cost ,但很奇怪太過量的展開有時候會有反效果.. 原來跟JIT運作有關?? MethodImplOptions.AggressiveInlining 這東西我在改專案時有看到, 但不知道做啥的... 後來就把它自己手動開展了..而且這東西好像.NET 4.0沒有 直接指標又會比ARRAY再快些? 我再確認看看...感謝 不過說真的...這種優化處理問題,真的有心,要到達極致,堅持純C#的話, 真的跟我想的一樣,IL跟JIT都要挖下去... 照理說C#還真的比較少做這種事情..像影音編解碼.video filter等等, 多數是c/c++天下. 另外像是GPU的搭配,C#也比較少討論到... 有小玩一下C#+OPENCL做過些測試... (用別人的套件...應該也是用INVOKE Native的方式) 沒寫好的話,光記憶體copy進入到vram,和vram copy出來到程式, 不然就是差不多時間,不然甚至更慢... opencl 2.0 虛擬共享記憶體目前好像沒看到c#套件有支援到... 這些東西似乎又是另一個世界就是... ※ 編輯: erspicu (118.171.212.174), 12/18/2015 17:43:34