Performance gfortran“-三月=哈斯韦尔“;慢于-三月=核心2“;
我在64位Windows7机器上运行gfortran 4.9.2,该机器采用Intel Core i5-4570(Haswell)。我在同一台机器上编译和执行 使用编译我的代码(科学模拟) 比使用Performance gfortran“-三月=哈斯韦尔“;慢于-三月=核心2“;,performance,gcc,x86,gfortran,Performance,Gcc,X86,Gfortran,我在64位Windows7机器上运行gfortran 4.9.2,该机器采用Intel Core i5-4570(Haswell)。我在同一台机器上编译和执行 使用编译我的代码(科学模拟) 比使用 gfortran -frecord-marker-4 -fno-automatic -O3 -fdefault-real-8 (...) -Wline-truncation -Wsurprising -ffpe-trap=invalid,zero,overflow (...)
gfortran -frecord-marker-4 -fno-automatic -O3 -fdefault-real-8 (...)
-Wline-truncation -Wsurprising -ffpe-trap=invalid,zero,overflow (...)
-march=haswell -mfpmath=sse -c
(-march=native
给出与-march=haswell
相同的结果)
这让我觉得很奇怪,因为我希望有更多的指令可以让代码更快,而不是更慢
第一:这是一台新机器,是我工作时旧机器的替代品,很不幸:
- 我无法再使用以前的处理器进行测试
- 对于我来说,使用另一个gfortran版本进行测试比安装的版本更困难
-march=
设置进行了一些评测(请参阅)。在本测试中:
,core2
,nehalem
都会导致~85秒Westmile
- 从
(添加AVX指令集)开始,执行时间跳到122s(对于sandybridge
,执行时间跳到128s)haswell
-march=core2的平面轮廓:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls us/call us/call name
8.92 6.18 6.18 __sinl_internal
8.50 12.07 5.89 __cosl_internal
7.26 17.10 5.03 _mcount_private
6.42 21.55 4.45 exp
6.41 25.99 4.44 exp2l
5.08 29.51 3.52 __fentry__
3.71 32.08 2.57 35922427 0.07 0.18 predn_
3.53 34.53 2.45 log2l
3.36 36.86 2.33 79418108 0.03 0.03 vxs_tvxs_
2.90 38.87 2.01 97875942 0.02 0.02 rk4m_
2.83 40.83 1.96 403671 4.86 77.44 radarx_
2.16 42.33 1.50 4063165 0.37 0.43 dchdd_
2.14 43.81 1.48 pow
2.11 45.27 1.46 8475809 0.17 0.27 aerosj_
2.09 46.72 1.45 23079874 0.06 0.06 snrm2_
1.86 48.01 1.29 cos
1.80 49.26 1.25 sin
1.75 50.47 1.21 15980084 0.08 0.08 sgemv_
1.66 51.62 1.15 61799016 0.02 0.05 x2acc_
1.64 52.76 1.14 43182542 0.03 0.03 atmostd_
1.56 53.84 1.08 24821235 0.04 0.04 axb_
1.53 54.90 1.06 138497449 0.01 0.01 axvc_
-march=haswell的平面剖面图
:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls us/call us/call name
6.49 6.71 6.71 __sinl_internal
6.05 12.96 6.25 __cosl_internal
5.55 18.70 5.74 _mcount_private
5.16 24.03 5.33 exp
5.14 29.34 5.31 cos
4.87 34.37 5.03 sin
4.67 39.20 4.83 exp2l
4.55 43.90 4.70 35922756 0.13 0.34 predn_
4.38 48.43 4.53 8475884 0.53 0.69 aerosj_
3.72 52.27 3.84 pow
3.43 55.82 3.55 __fentry__
2.79 58.70 2.88 403672 7.13 120.62 radarx_
2.64 61.43 2.73 79396558 0.03 0.03 vxs_tvxs_
2.36 63.87 2.44 log2l
1.95 65.89 2.02 97881202 0.02 0.02 rk4m_
1.80 67.75 1.86 12314052 0.15 0.15 axs_txs_
1.74 69.55 1.80 8475848 0.21 0.66 mvpd_
1.72 71.33 1.78 36345392 0.05 0.05 gauss_
1.53 72.91 1.58 25028687 0.06 0.06 aescudi_
1.52 74.48 1.57 43187368 0.04 0.04 atmostd_
1.44 75.97 1.49 23077428 0.06 0.06 snrm2_
1.43 77.45 1.48 17560212 0.08 0.08 txs_axs_
1.38 78.88 1.43 4062635 0.35 0.42 dchdd_
1.36 80.29 1.41 internal_modf
1.30 81.63 1.34 61800367 0.02 0.06 x2acc_
1.26 82.93 1.30 log
1.25 84.22 1.29 138497176 0.01 0.01 axvc_
1.24 85.50 1.28 15978523 0.08 0.08 sgemv_
1.10 86.64 1.14 10707022 0.11 0.11 ec_txs_
1.09 87.77 1.13 8475648 0.13 0.21 g_eval_
1.06 88.87 1.10 __logl_internal
0.98 89.88 1.01 17765874 0.06 0.07 solgeo_
0.98 90.89 1.01 15978523 0.06 0.06 sger_
您会注意到,使用-haswell
(甚至像sin/cos/exp这样的内部函数!)基本上一切都会变慢
我可以举一个代码示例,函数vxs\u tvxs
,它消耗2.73s和2.33s:
SUBROUTINE VXS_TVXS(VXS,TVXS)
REAL VXS(3),TVXS(3,3)
VTOT=sqrt(sum(VXS**2))
VH=sqrt(VXS(1)**2+VXS(2)**2)
if (VTOT==0.) then
print*,'PB VXS_TVXS : VTOT=',VTOT
stop
endif
sg=-VXS(3)/VTOT
cg=VH/VTOT
if (VH==0.) then
sc=0.
cc=1.
else
sc=VXS(2)/VH
cc=VXS(1)/VH
endif
TVXS(1,:)=(/ cg*cc, cg*sc, -sg/)
TVXS(2,:)=(/ -sc, cc, 0./)
TVXS(3,:)=(/ sg*cc, sg*sc, cg/)
RETURN
END
对我来说似乎是一个无害的功能
我做了一个非常简单的程序
PROGRAM PIPO
REAL VXS0(3),VXS(3),TVXS(3,3)
VXS0=(/50.,100.,200./)
VXS=VXS0
call cpu_time(start)
do k=1,50 000 000
call VXS_TVXS(VXS,TVXS)
VXS=0.5*(VXS0+TVXS(1+mod(k,3),:))
VXS=cos(VXS)
enddo
call cpu_time(finish)
print*,finish-start,VXS
END
不幸的是,在这个测试用例中,所有的-march
设置最终都有大约相同的时间要求
所以我真的不明白发生了什么。。。另外,正如我们从前面的简介中看到的,甚至内部功能的成本也越来越高,这一事实让人感到非常困惑。您能为花费大部分时间的零件分解两个版本并进行后期组装吗<如果使用-S
选项运行,code>gcc
将保存汇编代码,我不知道gfortran
是否相同。有很多asm专家经常访问这个网站,如果你能分析你的代码以找到“热点”并将其分解,很有可能有人会为你找到答案。如果只是“这是一个大程序,我不能给出任何细节或显示任何代码”,你就不会得到答案。在这种情况下,你可能会在另一个网站上有更好的运气;这个网站专门用来问一些有明确答案的问题。你使用的是什么版本的gfortran?如果不是最新版本,我建议升级到4.9.2并重试。如果您可以通过评测(通过-pg
选项和gprof
)找到一段代码,并且可以显示一段悲观的代码,我建议您将错误报告提交给。通过这种方式,gcc维护人员将了解这个问题,并且它有很好的修复机会(如果是回归,甚至更高,例如,如果相同的选项更早地生成更好的代码)。谢谢harold。我不熟悉如何生成相关的反汇编代码。我知道我应该在编译时使用-S,但是呢?此外,我还将进行一些附加测试,特别是使用非常简单的唯一vxs_tvxs函数。如果我能在一个测试程序上重现相同的行为,即简单地使用不同的值循环vxs_TVX一百万次,那么应该将其缩小到一个gcc/gfortran问题(同时也大大简化了研究,因为要处理的代码只有几行而不是>20k)听起来像是混合了AVX指令(您的程序)和SSE指令(libm),这可能会有很坏的惩罚(可能缺少vzeroupper?)。
PROGRAM PIPO
REAL VXS0(3),VXS(3),TVXS(3,3)
VXS0=(/50.,100.,200./)
VXS=VXS0
call cpu_time(start)
do k=1,50 000 000
call VXS_TVXS(VXS,TVXS)
VXS=0.5*(VXS0+TVXS(1+mod(k,3),:))
VXS=cos(VXS)
enddo
call cpu_time(finish)
print*,finish-start,VXS
END