为什么是去分支反而运行速度变慢了

int main()
{
    clock_t startTime, endTime;
    for (int s = 0; s < 100; s++)
    {
        int number[100];
        for (int i = 0; i < 100; i++)
        { 
            number[i]= (rand() % 100);
        }

        {
            
            int unm = 0;
            int max = 0;
            startTime = clock();
            for (int i = 0; i < 123456789; i++)
            {
                unm = (number[i%100] - 50) >> 31;
                max = (number[i % 100] & unm) + max;
            }
            endTime = clock();
            printf("优化CPU时间:%d tick 结果%d", endTime - startTime,max);
        }

        {
          
            int unm = 0;
            int max = 0;
            startTime = clock();
            for (int i = 0; i < 123456789; i++)
            {

                if (number[i % 100] < 50)
                {
                    max = number[i % 100] + max;
                }
            }
            endTime = clock();
            printf("非优化CPU时间:%d tick 结果%d\r\n", endTime - startTime,max);
        }
    }
    

    return 0;
}

上述代码运行

运行结果

 

这里运行时间的主要因素是每次循环计算的区别。

1)去分支:

                unm = (number[i % 100] - 50) >> 31;
                max = (number[i % 100] & unm) + max;

2次取模:i % 100 假设结果为m

2次数组小标寻址:number[m],假设结果问n

以上两个2次,编译器能优化成各1次。

1次减法 n - 50,假设结果为s

1次移位 s >> 31,结果位unm

1次按位与 n & unm,假设结果位 a

1次加法 a + max

共6次运算。其实取模的开销大于加减法大于按位与和移位。

 

2)有分支:

                if (number[i % 100] < 50) {
                    max = number[i % 100] + max;
                }

每次循环必须有的运算:

1次取模:i % 100 假设结果为m

1次数组小标寻址:number[m],假设结果问n

1次小于比较 n < 50

当 n < 50 时还有1次加法 n + max。(number[i % 100]编译器可以优化用if条件判断计算时的值)。

所以每次循环只有3次或者3次运算。

所以有分支的代码运算更快。去分支的代码,我认为不但性能差些,可读性也差些,不鼓励这样写代码。