作者littleshan (我正在想要换什麽)
看板C_and_CPP
标题Re: [问题] 两层for回圈的效果
时间Sat May 27 00:53:01 2017
实验最快
#include <stdio.h>
#include <stdint.h>
inline uint64_t rdtsc(
void)
{
uint32_t hi, lo;
asm volatile (
"rdtsc" :
"=a"(lo),
"=d"(hi));
return ((
uint64_t)lo) | (((
uint64_t)hi)<<
32);
}
uint64_t calc(
uint64_t outer,
uint64_t inner)
{
uint64_t s =
0;
for(
uint64_t i =
1; i <= outer; ++i){
for(
uint64_t j =
1; j <= inner; ++j){
s += i*j;
}
}
return s;
}
int main()
{
uint64_t t0 = rdtsc();
uint64_t sum1 = calc(
100ul,
1000000ul);
uint64_t t1 = rdtsc();
uint64_t sum2 = calc(
1000000ul,
100ul);
uint64_t t2 = rdtsc();
printf(
"sum1 = %lu, used %lu cycles\n", sum1, t1-t0);
printf(
"sum2 = %lu, used %lu cycles\n", sum2, t2-t1);
return 0;
}
使用 gcc 6.3 用 -O2 编译
执行环境 Linux 4.9.18 with Intel Core i5-7260U
结果:
sum1 = 2525002525000000, used 356 cycles
sum2 = 2525002525000000, used 2633286 cycles
造成这样差异的原因,是 gcc 把 calc() 函式直接 inline
然後展开内层回圈的运算结果
第一个 function call 转为 asm 後长这样:
movabsq $
500000499999, %
rdx
movq %
rdx, %
rdi
.p2align 4,,
10
.p2align 3
.L15:
leaq (%
rdx,%
rax), %
rcx
addq $
1, %
rax
addq %
rdi, %
rdx
addq %
rcx, %
rsi
cmpq $
101, %
rax
jne .L15
看起来有点复杂,翻回 C 就是这样:
rax =
1;
rdx =
500000499999;
do{
rcx = rdx + rax;
rdx +=
500000499999;
sum += rcx;
rax++;
}
while(rax !=
101);
我不知道为什麽不直接加 500000500000 就好,不过这不是重点
重点是这样回圈只跑了 100 次
相较於第二个 function call,同样的展开方式回圈会跑 1000000 次
当然是第一种方式比较快,而且也很刚好差了一万倍左右
不过这一切都取决於 compiler 最佳化
未来会不会不管怎麽呼叫都直接在 compile time 算出答案给你,其实很有可能
到时候两种作法就一样快了
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 114.25.242.143
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1495817584.A.C52.html
1F:推 Hazukashiine: 推实验精神 05/27 01:18
2F:推 mh2ant: 好猛 05/27 11:49
3F:推 cuteSquirrel: 推 动手做! 05/27 19:34
4F:推 shadow0326: 推 05/28 13:16
5F:推 xxxx9659: 好猛!! 06/04 14:49