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次运算。
所以有分支的代码运算更快。去分支的代码,我认为不但性能差些,可读性也差些,不鼓励这样写代码。