zoukankan      html  css  js  c++  java
  • 数学运算比IF要快

    问题

    虽然很早就知道,CPU在处理 if 这样的判断语句时,使用了预测的技术,所以如果条件总是一个结果,效率就很好。反过来说,如果你使用数学运算避免 if 判断,那么就意味着性能一定比 if 要好。

    方案1

    今天正好有个函数遇到这个问题,所以我就正好测试以下。

    待测试的方法是获取一个int32的数据中,有多少个位是 1,我的方案是将 一个int32拆开成 4个字节,然后一一判断。下面是使用 if 判断的方案 (那个  ? : 三元运算符就是 if 语句)。

     1 static int getInt32TrueCount(int value)
     2 {
     3     if (value == 0)
     4     {
     5         return 0;
     6     }
     7 
     8     return getByteTrueCount(value & 0xFF) +
     9         getByteTrueCount((value >> 8) & 0xFF) +
    10         getByteTrueCount((value >> 16) & 0xFF) +
    11         getByteTrueCount((value >> 24) & 0xFF);
    12 }
    13 
    14 static int getByteTrueCount(int value)
    15 {
    16     if (value == 0)
    17     {
    18         return 0;
    19     }
    20 
    21     int a = (value & 0x1) == 0 ? 0 : 1;
    22     int b = (value & 0x2) == 0 ? 0 : 1;
    23     int c = (value & 0x4) == 0 ? 0 : 1;
    24     int d = (value & 0x8) == 0 ? 0 : 1;
    25 
    26     int e = (value & 0x10) == 0 ? 0 : 1;
    27     int f = (value & 0x20) == 0 ? 0 : 1;
    28     int g = (value & 0x40) == 0 ? 0 : 1;
    29     int h = (value & 0x80) == 0 ? 0 : 1;
    30 
    31     return a + b + c + d + e + f + g + h;
    32 }

    可以看到, 每运算一个位都有一个 if 判断,而要命的是这个 if 判断的结果是不稳定的,随机性极大。我写了一个计时程序,在我计算机中需要 12秒。(i5 6500 Release .net core 2.0 )

     1 static void GetBitCountTest()
     2 {
     3     var wathch = Stopwatch.StartNew();
     4             
     5     var rand = new Random();
     6 
     7     for (int i = 0; i < 10000_0000; i++)
     8     {
     9         int value = rand.Next();
    10         int p = getInt32TrueCount(value);
    11     }
    12 
    13     wathch.Stop();
    14     Console.WriteLine("GetBitCount 耗时:" + wathch.Elapsed.ToString());
    15 
    16 }

    方案2

    第二种方法就是将 if 判断改为数学运算,方法是将 and 运算后的位 移动到 0位,这样就是 0 或 1 了。

     1 static int getInt32TrueCount2(int value) {
     2     if (value == 0) {
     3         return 0;
     4     }
     5 
     6     return getByteTrueCount2(value & 0xFF) +
     7         getByteTrueCount2((value >> 8) & 0xFF) +
     8         getByteTrueCount2((value >> 16) & 0xFF) +
     9         getByteTrueCount2((value >> 24) & 0xFF);
    10 }
    11 
    12 static int getByteTrueCount2(int value) {
    13     return (value & 0x1) +
    14             ((value & 0x2) >> 1) +
    15             ((value & 0x4) >> 2) +
    16             ((value & 0x8) >> 3) +
    17 
    18             ((value & 0x10) >> 4) +
    19             ((value & 0x20) >> 5) +
    20             ((value & 0x40) >> 6) +
    21             ((value & 0x80) >> 7);
    22 }

    再次运行测试用例,执行时间提高到 2 秒!提高了6倍。

    总结:

    高性能计算时,避免使用 分支 指令,尽量使用数学运算符。

  • 相关阅读:
    Asp.NET 4.0 ajax实例DataView 模板编程1
    ASP.NET 4.0 Ajax 实例DataView模板编程 DEMO 下载
    部分东北话、北京话
    .NET 培训课程解析(一)
    ASP.NET 4.0 Ajax 实例DataView模板编程2
    ASP.NET Web Game 架构设计1服务器基本结构
    ASP.NET Web Game 构架设计2数据库设计
    TFS2008 基本安装
    Linux上Oracle 11g安装步骤图解
    plsql developer远程连接oracle数据库
  • 原文地址:https://www.cnblogs.com/tansm/p/AvoidTheUseOfIf.html
Copyright © 2011-2022 走看看