总的来说,浮点应用有以下几个考量目标
- 精度:应用最后计算出的结果与理论结果一致.
- 可重复性及可移植性:应用在多个平台或架构上,多次运行的结果依然保持一致相同.
- 性能:应用计算所需的运行时间.
用户在编写含浮点计算的应用时,应在以上的考量目标中做适当的折中。例如,在开发3D图形引擎的情况下,性能可能是要考虑的最重要的因素,并且可重现性及精度可能是相对次要的考量因素。
Intel® C++ Compiler 提供了对应的编译器选项来允许开发者更好地调优自己的浮点程序。大致来说,这些编译器选项包括-fp-model (Linux* and OS X*) 及 /fp (Windows*) ,以及用于加快速度而牺牲部分精度的[Q]imf-max-error选项。在开发者指定不同的编译选项时,编译器会对应做不同的优化及代码生成,所以此时需要开发者在调优程序时要结合自己的程序要达到的目标来合理地选择适合的编译选项搭配,而且指定的某些编译选项也会影响到编译器自动生成对相关精度的数学函数的调用,比如Intel® C++ Compiler会自动链接到对libirc, libm, 及svml等高性能函数库的调用。
1. 使用-fp-model浮点选项
在以下的代码示例中
float t0, t1, t2; ... t0=t1+t2+4.0f+0.1f;
当指定-fp-model extended (Linux* and OS X*)或/fp:extended (Windows*)选项时,编译器将会产生对应的最高精度的汇编指令
fld DWORD PTR _t1 fadd DWORD PTR _t2 fadd DWORD PTR _Cnst4.0 fadd DWORD PTR _Cnst0.1 fstp DWORD PTR _t0
以上的代码会最大化精度因为编译时会生成所对应目标平台上可用的最高尾数精度,然而代码此时会因使用X87硬件栈而产生部分性能损失,而且这种情况下生成的代码在其它不支持对应扩展精度的处理器上可能不会重现精确的浮点计算结果。
当指定-fp-model source (Linux* and OS X*)或/fp:source (Windows*)选项时,编译的代码会确保可重现性及可移植性,比如产生的以下代码
movss xmm0, DWORD PTR _t1 addss xmm0, DWORD PTR _t2 addss xmm0, DWORD PTR _Cnst4.0 addss xmm0, DWORD PTR _Cnst0.1 movss DWORD PTR _t0, xmm0
会通过保证浮点计算的初始顺序及使用规范的IEEE单精度类型定义来确保最大化程序的可移植性。在这种情况下,由于计算时的中间结果的舍入,该程序运行时的结果可能不会与上一个浮点选项所确保的精度一样,并且由于此时编译器不会预先计算4.0f + 0.1f的值,该程序的运行时性能也不会达到最优。
当指定-fp-model fast (Linux* and OS X*) 或 /fp:fast (Windows*) 选项时,此时编译器会产生更高性能的代码,比如
movss xmm0, DWORD PTR _Cnst4.1 addss xmm0, DWORD PTR _t1 addss xmm0, DWORD PTR _t2 movss DWORD PTR _t0, xmm0
以上的代码会通过使用Intel® SSE 多媒体指令以及编译时预计算4.0f + 0.1f来更高地提升性能。此时,由于中间结果的舍入,程序的结果不会像使用第一个浮点选项一样精确;而且由于编译器会重新排序浮点加法以便预计算4.0f + 0.1f的值,程序的结果的可重现性也会低于使用第二个浮点选项时所产生的代码;并且编译器的不同版本以及不同的优化等级也会导致对此浮点计算的不同程度的优化,从而也会导致一定程序的可重现性的影响。
2. 使用fast-but-low-accuracy选项
使用fast-but-low-accuracy选项可以控制Intel® Math 函数库中所提供的各种数学函数的精度,开发者只需要通过改变对应的编译选项来更好地调优程序。例如,可以通过指定此选项的max-error属性来选择函数库中的适合的数学函数:
-fimf-max-error=2
以上的选项会对所有的单精度, 双精度等浮点数指定2 ulps(最小精度单位)的相对结果。
开发者也可以特别指定Sin函数的精度为12位,比如
–fimf-sin-accuracy-bits=12
更进一步调优的话,比如指定Sin函数的ulps为10,且其它的数学函数为4个精度单位,可以使用一下编译选项:
-fimf-sin-max-error=10 -fimf-max-error=4
Intel® C++ Compiler通过用户对/fp 及/Qfast-transcendentals选项的设置来定义缺省的max-error属性的值,比如/Qfast-transcendentals会使能/fp:fast选项以及设置max-error=4。