zoukankan      html  css  js  c++  java
  • 深入探讨用位掩码代替分支(9):测试成绩总结

    一、测试结果汇总

      将前面的测试结果进行汇总,整理为表格(单位是毫秒,数值越小越好)——

    测试 f0_if f1_min f2_neg f3_sar f4_mmx f5_sse
    VC6 on 32bit 2016 2063 719 672 37.5 25.7
    VC6 on 64bit 2028 2075 718 687 37.1 25.3
    VC2010(32) on 32bit 1793 2112 512 437    
    VC2010(32) on 64bit 1716 2106 514 437    
    VC2010(64) on 64bit 1623 1997 421 328    
    C#2010(any) on 32bit 1922 2147 2471 559    
    C#2010(any) on 64bit 1871 1918 2406 651    
    C#2010(x86) on 32bit 1930 2142 2462 545    
    C#2010(x86) on 64bit 1829 2073 2340 516    
    C#2010(x64) on 64bit 1865 1911 2399 651    
    VB6 on 32bit 2844   1078      
    VB6 on 64bit 2839   1061      

    注:CPU:Intel Core i3-2310M, 2100 MHz。

      对应图表——

      上图是以毫秒为单位,因数据量很多,看起来有点吃力。于是又做了一个表格,将各列的数据除以“f0_if”列,即以倍数为单位,数值越大越好——|

    测试 f0_if f1_min f2_neg f3_sar f4_mmx f5_sse
    VC6 on 32bit 1.00 0.98 2.80 3.00 53.76 78.44
    VC6 on 64bit 1.00 0.98 2.82 2.95 54.66 80.16
    VC2010(32) on 32bit 1.00 0.85 3.50 4.10    
    VC2010(32) on 64bit 1.00 0.81 3.34 3.93    
    VC2010(64) on 64bit 1.00 0.81 3.86 4.95    
    C#2010(any) on 32bit 1.00 0.90 0.78 3.44    
    C#2010(any) on 64bit 1.00 0.98 0.78 2.87    
    C#2010(x86) on 32bit 1.00 0.90 0.78 3.54    
    C#2010(x86) on 64bit 1.00 0.88 0.78 3.54    
    C#2010(x64) on 64bit 1.00 0.98 0.78 2.86    
    VB6 on 32bit 1.00   2.64      
    VB6 on 64bit 1.00   2.68      

      对应图表(因MMX/SSE的性能太鹤立鸡群,影响图表阅读,故省略)——

    二、各算法的性能分析

      现在我们按照列顺序(即各个算法的顺序)来进行分析——
    1.首先,f0_if是采用if语句的基础算法,当作标杆用来评比其他算法。
    2.f1_min采用了系统函数min、max。因现代编译器会对min、max做内联优化的,理论上应该与f0_if差不多。但实际测试后发现,f1_min比f0_if慢了一些。原因可能是因为min/max的语义与if不同,编译优化的深度不及if语句。
    3.f2_neg算法采用了位运算来避免分支跳转,处理速度有了较大提高,平均性能大约是f0_if的3倍。可惜C#不支持将bool型强制转换为整型,而调用Convert.ToInt16带来了性能开销,使其比f0_if还慢。
    4.f3_sar算法利用带符号移位避免了状态寄存器的访问,处理速度又有了一定的提升,平均性能大约是f0_if的3.5倍。
    5.f4_mmx、f5_sse算法因为用到MMX、SSE这些SIMD指令集,所以处理速度比前面那些高级语言算法高了一个级别。

    算法 最小倍数 最大倍数 平均倍数 备注
    f1_min 0.81 0.98 0.91 无VB6
    f2_neg 2.64 3.86 3.09 无C#
    f3_sar 2.86 4.95 3.52 无VB6
    f4_mmx 53.76 54.66 54.21 仅VC6
    f5_sse 78.44 80.16 79.3 仅VC6


    三、其他发现

      分析测试结果,还发现——
    1.VC2010的的编译优化能力比VC6要强,同样程序的运行速度要快很多。这可能是因为VC2010的编译优化更能适应最新处理器的指令级并行性。
    2.在64位系统中能运行32位程序,除了C#以外,其运行速度与在32位系统中的差不多。
    3.C#2010的程序,有时在64位系统上的运行速度比32位系统还慢,甚至包括了“x64”平台方式编译的程序。似乎“x86”平台方式编译的程序的平均性能最好。可能是因为64位JIT(即时编译器)不如32位的成熟。
    4.对于VC2010编译器来说,编译的64位程序比32位程序的运行速度有比较明显的提升。看来编写64位程序的最好还是用VC等C/C++编译器。
    5.在传统印象中,VB、C#的运行速度比C语言慢很多。但通过这次测试发现,虽然它们的性能是有一定差距,但是是处于同一级别的,甚至C#与VC6打平还略占优势。影响程序运算速度的最关键因素是算法,用编译能力最差的VB6实现的f2_neg,比编译能力最好的VC2010实现的f0_if要快得多。


    四、总结

      使用位掩码代替分支能带来较大的性能提升,而且该方案能推广到任何高级语言,能充分利用高级语言的可移植性,能满足大多数的性能优化需求。
      但当对性能要求极高、且不要求可移植性时,强烈推荐MMX、SSE等SIMD指令集,能使处理速度提高一个级别。

    附:测试程序打包下载——

    https://files.cnblogs.com/zyl910/noif_Test.rar
    http://dl.dbank.com/c069c6thd7


    (完)


    《深入探讨用位掩码代替分支》系列文章——
    1、利用带符号移位生成掩码:http://www.cnblogs.com/zyl910/archive/2012/03/12/noifopex1.html
    2、汇编代码分析:http://www.cnblogs.com/zyl910/archive/2012/03/21/noifopex2.html
    3、VC6速度测试:http://www.cnblogs.com/zyl910/archive/2012/03/27/noifopex3.html
    4、VC2010速度测试:http://www.cnblogs.com/zyl910/archive/2012/03/28/noifopex4.html
    5、C#2010速度测试:http://www.cnblogs.com/zyl910/archive/2012/03/29/noifopex5.html
    6、VB6速度测试:http://www.cnblogs.com/zyl910/archive/2012/03/30/noifopex6.html
    7、MMX指令集速度测试:http://www.cnblogs.com/zyl910/archive/2012/04/09/noifopex7.html
    8、SSE指令集速度测试:http://www.cnblogs.com/zyl910/archive/2012/04/12/noifopex8.html
    9、测试成绩总结:http://www.cnblogs.com/zyl910/archive/2012/04/13/noifopex9.html

  • 相关阅读:
    F. 数学上来先打表
    LibreOJ β Round #2
    noip飞扬的小鸟
    jxoi2017
    分块算法
    Chino的数列
    cf 613E
    cf 126D
    cf 542E
    cf 512D
  • 原文地址:https://www.cnblogs.com/zyl910/p/noifopex9.html
Copyright © 2011-2022 走看看