Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29252 Discussions

Reducing noise for Real(8) divisions

mattsdad
Beginner
1,027 Views
The default behavior is to use a fast but aproximate division in Fortran. What flag sets this feature to the most accurate division?

Is it possible to set this flag on a unit by unit basis?
0 Kudos
5 Replies
mattsdad
Beginner
1,027 Views

I might add that we did get a very significant reduction in noise by setting result variables to 0.0d0 before calculations as below, but we have one algorithm that needs to be much more consistent.

FUNCTION div(a, b) RESULT(c)
REAL(8), INTENT(IN) :: a, b
REAL(8) :: c

c = 0.0d0

c = a / b

END FUNCTION div

0 Kudos
Steven_L_Intel1
Employee
1,027 Views
Try /fp:precise You can specify this on a source by source basis.
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,027 Views
Matt,

The compiler optimizations (assuming you do optimize) should eliminate the "c = 0.0d0" in the above example.

Assuming something else is inserted there that is not optimized out. The something else could coerce the rounding of 0.5 bit to always be in one direction (as opposed to in a random direction).

The "stability" you observe may come at the expense of accuracy of the overall approximation.

Jim
0 Kudos
mecej4
Honored Contributor III
1,027 Views
With IFort, by default optimization is turned on. Your function, compiled for X64, gives exactly three instructions:

[bash]0000000000000000 :
   0:   f2 0f 10 07             movsd  (%rdi),%xmm0 # load a
4: f2 0f 5e 06 divsd (%rsi),%xmm0 # divide by b
8: c3 retq [/bash]
On IA-32, likewise:
[bash]00000000 :
   0:   83 ec 08                sub    $0x8,%esp
   3:   8b 44 24 0c             mov    0xc(%esp),%eax
   7:   8b 54 24 10             mov    0x10(%esp),%edx
   b:   f2 0f 10 00             movsd  (%eax),%xmm0 # load a
f: f2 0f 5e 02 divsd (%edx),%xmm0 # divide by b
13: f2 0f 11 04 24 movsd %xmm0,(%esp) 18: dd 04 24 fldl (%esp) 1b: 83 c4 08 add $0x8,%esp 1e: c3 ret
[/bash]
Thus, your assignment c = 0.0d0 has been removed by the optimizer, and its presence in the source code should have no effect on results.

I do not understand what you mean by "noise" in a non-physical context. If the introduction of do-nothing statements is causing a change to the significant results of a calculation, I suspect that there are bugs in the algorithm or the implementation.
0 Kudos
TimP
Honored Contributor III
1,027 Views
/Qprec-div prevents the compiler from using an iterative sequence to increase throughput for division. The iterative sequence has unpredictable rounding, affecting the last bit of precision, and may fail (produce NaN or 0.) when dividing operands of very large or small magnitude. Normally, that non-IEEE accurate sequence would be used only for single precision vectorization.
/Qprec-sqrt prevents the analogous iteration for sequences involving sqrt() or 1/sqrt().
Those /Qprec- options are included in /fp:source and similar options, as Steve mentioned.
The usual way of changing these flags among units of a build is by Makefile or splitting projects.
As the less consistent method tends to be associated with vectorization, it should be possible to get the IEEE accurate result at the expense of performance by employing !dir$ no vector directives for vectorizable loops containing division, but I couldn't recommend that, as the IEEE accurate /Qprec-div vectorization normally performs well with all CPUs in current production.
0 Kudos
Reply