作者erspicu (.)
看板C_Sharp
标题[闲聊] video filter 效能
时间Thu Dec 17 12:24:53 2015
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://webptt.com/cn.aspx?n=bbs/C_Sharp/M.1450326300.A.BC8.html
1F:→ fo40225: 要更快就要用unsafe去存取array与bitmap 12/17 22:46
真的有仔细看内文和稍微看一下专案的内容吗...
※ 编辑: erspicu (61.70.74.143), 12/18/2015 00:18:49
2F:→ 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;
如果你真的对这专案.议题.文章没兴趣,东西真的可以不需要看一半.
3F:→ fo40225: .net4.6 x64可以用CPU SIMD加速 那些矩阵处理也可以更快 12/18 12:56
4F:→ 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
5F:→ Litfal: 如果是相容考量,C++应该更好一些,不过得看你相容什麽XD 12/18 16:35
恩 相容的定义其实看那种性质的相容
6F:→ Litfal: 然後filter系的优化,可以用动态产生IL的技巧,把一些不必 12/18 16:36
7F:→ Litfal: 要的运算直接去掉,例如x1、x0、x-1这种在filter里面常出 12/18 16:37
8F:→ Litfal: 现的。直接动态产生IL的方式,我比较推荐Expression Tree 12/18 16:39
9F:→ Litfal: 自己写IL code有点辛苦,虽然有时是必要的... 12/18 16:39
IL code不太熟...不过我猜应该跟我之前k java bytecode大同小异
以後再慢慢看看....
10F:→ fo40225: 文章 专案没看懂是我的问题 抱歉 12/18 16:43
11F:→ fo40225: 但我认为在ScaleImage内的操作 展开成那样 12/18 16:45
12F:→ fo40225: JIT的优化都没了 还不如用unsafe + SIMD 可读会回来一些 12/18 16:46
13F:→ fo40225: 这样也还算是在C#内实作吧?毕竟unsafe操作指标也是C#规格 12/18 16:47
14F:→ fo40225: 如果操作array是瓶颈那就用unsafe去改 12/18 16:49
15F:→ fo40225: 都用上pfor平行操作多笔资料了 用上SIMD一次操作更多不是 12/18 16:52
16F:→ fo40225: 用pfor操作还有可能有CPU cache miss问题 12/18 16:57
17F:→ fo40225: 展开减少stack push pop也可以试试MethodImplOptions 12/18 17:04
18F:→ 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