Linux c 程序性能分析问题,有大佬能解释一下为何这段代码在 3700x 上很慢,而在 5600x 上很快吗?

2022-04-06 15:39:46 +08:00
 kgdb00
// cpu-test.c
#include <math.h>

int main(int argc, char *argv[])
{
	unsigned long long c;
	unsigned long long l;
	double t;

	for (c = 3; c < 1000000; c++) {
		t = sqrt((double) c);
		for (l = 2; l <= t; l++)
			if (c % l == 0)
				break;
	}

	return 0;
}

这段代码取自 sysbench ,略有删减,原函数是:

https://github.com/akopytov/sysbench/blob/master/src/tests/cpu/sb_cpu.c 的 cpu_execute_event 函数。

使用"perf stat ./cpu-test"在 3700x 上得到的 IPC 是 0.83 ,而在 5600X 上得到的是 2.23 。

5420 次点击
所在节点    Linux
33 条回复
kgdb00
2022-04-06 15:51:24 +08:00
使用"sysbench cpu run"得到的是同样的结果,5600x 上的性能要远高于 3700x 。
booboo
2022-04-06 15:55:39 +08:00
是否确保编译出来的程序是一样(汇编代码比较),再就是你用了 sqrt 是动态链接的话库是否一致,操作系统版本和编译项是否一样。
一般性能差这么大,大概率是缓存引起的。
Huelse
2022-04-06 16:00:26 +08:00
据我所知,锐龙 5000 系列是新架构,三缓利用效率对比前几代提升很大,也就是单核性能很强

你都是 long long 类型的,占用比较大,此时三缓越快越明显
askonly
2022-04-06 16:02:44 +08:00
@booboo 感谢回复,编译出的程序是一样的,都是在 fedora 35 系统上,而且用 fedora 35 的 sysbench 也是这样的差距。
kgdb00
2022-04-06 16:03:59 +08:00
@booboo 感谢回复,编译出的程序是一样的,都是在 fedora 35 系统上,而且用 fedora 35 的 sysbench 也是这样的差距。刚才不小心用小号回复了。
icyalala
2022-04-06 16:15:30 +08:00
先把 branches, branch-misses, L1-dcache-loads, L1-dcache-load-misse 都打出来看看。
这段代码没什么访存压力,无非是 sqrt 里面可能有些查表操作,warmup 后应该都在 L1 内。
排除编译差别,我感觉更可能是分支预测器表现不同,但还是要看 perf 输出结果。
jdjingdian
2022-04-06 16:25:29 +08:00
不懂性能分析,但是 3700x 是 zen2 ,5600x 是 zen3 ,5600x 单核性能高出 3700x 一大截
kgdb00
2022-04-06 16:25:41 +08:00
@icyalala
在 3700x 上运行"perf stat ./cpu-test"结果如下:

```
root@develop:~/test# perf stat ./cpu-test

Performance counter stats for './cpu-test':

313.31 msec task-clock # 0.999 CPUs utilized
0 context-switches # 0.000 /sec
0 cpu-migrations # 0.000 /sec
62 page-faults # 197.886 /sec
1,334,724,216 cycles # 4.260 GHz
4,152,400 stalled-cycles-frontend # 0.31% frontend cycles idle
1,084,407,060 stalled-cycles-backend # 81.25% backend cycles idle
1,112,064,247 instructions # 0.83 insn per cycle
# 0.98 stalled cycles per insn
280,732,961 branches # 896.020 M/sec
479,493 branch-misses # 0.17% of all branches

0.313649907 seconds time elapsed

0.313436000 seconds user
0.000000000 seconds sys
```

5600x 上结果如下:

```
d@desktop:~/test$ perf stat ./cpu-test

Performance counter stats for './cpu-test':

109.50 msec task-clock:u # 0.997 CPUs utilized
0 context-switches:u # 0.000 /sec
0 cpu-migrations:u # 0.000 /sec
57 page-faults:u # 520.552 /sec
497,192,700 cycles:u # 4.541 GHz
1,236,868 stalled-cycles-frontend:u # 0.25% frontend cycles idle
3,047 stalled-cycles-backend:u # 0.00% backend cycles idle
1,109,781,743 instructions:u # 2.23 insn per cycle
# 0.00 stalled cycles per insn
280,305,908 branches:u # 2.560 G/sec
420,708 branch-misses:u # 0.15% of all branches

0.109816486 seconds time elapsed

0.108714000 seconds user
0.000997000 seconds sys
```
kgdb00
2022-04-06 16:27:28 +08:00
@kgdb00 #8 v 站的回复不能用 markdown 格式化
choury
2022-04-06 16:38:26 +08:00
从 stalled-cycles-backend 上看,是浮点数性能差异比较大
icyalala
2022-04-06 17:13:32 +08:00
分支预测没什么太大差距。
如果同楼上浮点数性能差异的话,那就把其他都去掉,只测一下 sqrt() 看看,还有 fp 转 int 也可以单独测一下。
看了下 agner.org 的描述,Zen3 对 FP 单元提升挺大。
kgdb00
2022-04-06 17:44:52 +08:00
@choury @icyalala 我觉得应该跟浮点数性能没关系,我把 if (c % l == 0) 这一行去掉,3700x 的 ipc 还反超了 5600x 。

而且我用 perf annotate 分析 ,if (c % l == 0) 这一行的汇编指令有一条 mov %rdx,%rax 在 3700X 上占了 81%的时间,在 5600x 上也占了 54%的时间。

有没有什么办法让 perf record 的输出能在另一台机上分析?我发现拷贝 perf.data 到另一台机就不能 annotate 了,所以也没法共享给各位分析。
BrettD
2022-04-06 17:49:41 +08:00
把完整的 annotated assembly 贴出来?
kgdb00
2022-04-06 17:58:12 +08:00
kgdb00
2022-04-06 18:00:20 +08:00
3700X:
[Imgur]( )

5600X:

[Imgur]( )
secondwtq
2022-04-06 18:37:44 +08:00
这问题在这扯过了 https://v2ex.com/t/828141
BrettD
2022-04-06 18:38:57 +08:00
> 而且我用 perf annotate 分析 ,if (c % l == 0) 这一行的汇编指令有一条 mov %rdx,%rax 在 3700X 上占了 81%的时间,在 5600x 上也占了 54%的时间。

我觉得热点显示的 mov %rdx,%rax 这一行是在等上一条 divq 指令的 rdx 余数结果出来,然后 3700X 的整数除法运算可能比 5600X 慢,所以

> 把 if (c % l == 0) 这一行去掉,3700x 的 ipc 还反超了 5600x 。
secondwtq
2022-04-06 18:54:23 +08:00
@BrettD
> 我觉得热点显示的 mov %rdx,%rax 这一行是在等上一条 divq 指令的 rdx 余数结果出来

这是数据采集机制导致的误差,关键词 "skid"
choury
2022-04-06 22:17:41 +08:00
为什么不是编绎好的同一份二进制在两台机器上测呢,你这逻辑都不一样,测鬼呢
kgdb00
2022-04-06 22:38:38 +08:00
@choury 你为什么会认为我在两台机器上测的不是同一个二进制文件?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/845257

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX