[閒聊] video filter 效能

看板C_Sharp (C#)作者 (.)時間9年前 (2015/12/17 12:25), 9年前編輯推噓0(0018)
留言18則, 2人參與, 最新討論串1/1
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

12/17 22:46, , 1F
要更快就要用unsafe去存取array與bitmap
12/17 22:46, 1F
真的有仔細看內文和稍微看一下專案的內容嗎... ※ 編輯: erspicu (61.70.74.143), 12/18/2015 00:18:49

12/18 12:55, , 2F
我看了啊 看到都是用SetPixel 這就慢啊
12/18 12:55, 2F
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; 如果你真的對這專案.議題.文章沒興趣,東西真的可以不需要看一半.

12/18 12:56, , 3F
.net4.6 x64可以用CPU SIMD加速 那些矩陣處理也可以更快
12/18 12:56, 3F

12/18 12:59, , 4F
如果計算量夠大 用C++AMP寫邏輯給C#用可以比pfor快
12/18 12:59, 4F
文章開頭就寫到 "通常要求即時性的vidoe filter應該少會用全C#去實作, 不過一方面是為了好奇.一方面是挑戰C#效能極限.一方面是相容考量," 然後下面推文寫說可以插C++進去....... ※ 編輯: erspicu (118.171.212.174), 12/18/2015 13:52:59

12/18 16:35, , 5F
如果是相容考量,C++應該更好一些,不過得看你相容什麼XD
12/18 16:35, 5F
恩 相容的定義其實看那種性質的相容

12/18 16:36, , 6F
然後filter系的優化,可以用動態產生IL的技巧,把一些不必
12/18 16:36, 6F

12/18 16:37, , 7F
要的運算直接去掉,例如x1、x0、x-1這種在filter裡面常出
12/18 16:37, 7F

12/18 16:39, , 8F
現的。直接動態產生IL的方式,我比較推薦Expression Tree
12/18 16:39, 8F

12/18 16:39, , 9F
自己寫IL code有點辛苦,雖然有時是必要的...
12/18 16:39, 9F
IL code不太熟...不過我猜應該跟我之前k java bytecode大同小異 以後再慢慢看看....

12/18 16:43, , 10F
文章 專案沒看懂是我的問題 抱歉
12/18 16:43, 10F

12/18 16:45, , 11F
但我認為在ScaleImage內的操作 展開成那樣
12/18 16:45, 11F

12/18 16:46, , 12F
JIT的優化都沒了 還不如用unsafe + SIMD 可讀會回來一些
12/18 16:46, 12F

12/18 16:47, , 13F
這樣也還算是在C#內實作吧?畢竟unsafe操作指標也是C#規格
12/18 16:47, 13F

12/18 16:49, , 14F
如果操作array是瓶頸那就用unsafe去改
12/18 16:49, 14F

12/18 16:52, , 15F
都用上pfor平行操作多筆資料了 用上SIMD一次操作更多不是
12/18 16:52, 15F

12/18 16:57, , 16F
用pfor操作還有可能有CPU cache miss問題
12/18 16:57, 16F

12/18 17:04, , 17F
展開減少stack push pop也可以試試MethodImplOptions
12/18 17:04, 17F

12/18 17:04, , 18F
MethodImplOptions.AggressiveInlining
12/18 17:04, 18F
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
文章代碼(AID): #1MSZaSl8 (C_Sharp)
文章代碼(AID): #1MSZaSl8 (C_Sharp)