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

Reset MXCSR status (SSE)

ferrad01
Beginner
2,439 Views
I am getting a change of status of the MXCSR SSE flag when I do an innocuous multiplication of 2 numbers:

fdenth = fdenth * fdenth2

where:
fdenth = 25.0412656787643
fdenth2 = -10375445.7028794

both double precision variables.

MXCSR changes from 00001F80 to 00001FA0, which looks like the Precision bit.

Ordinarily I wouldn't worry about this, but these status values are tracked by a calling program (not ours) which is flagged in their software.

I have tried shuffling around the code to no avail, so I must ask if I can somehow reset this flag back to 00001F80 before I return?

Debug code, no optimization.
0 Kudos
5 Replies
Steven_L_Intel1
Employee
2,439 Views
Here's the description of that flag:

The inexact-result exception (also called the precision exception) occurs if the result
of an operation is not exactly representable in the destination format. For example,
the fraction 1/3 cannot be precisely represented in binary form. This exception
occurs frequently and indicates that some (normally acceptable) accuracy has been
lost. The exception is supported for applications that need to perform exact arithmetic
only. Because the rounded result is generally satisfactory for most applications,
this exception is commonly masked.

In other words, it is very common to have this flag set and normally it should be ignored. I haven't tried this but wonder if doing some multiply such as 2*2 (might be a bit tricky to get the compiler to actually emit the instruction) might clear the flag. There is an instruction to load the register but you'd have to do it from C or assembler.
0 Kudos
ferrad01
Beginner
2,439 Views
How can I mask it in the code so that the calling application doesn't see it?

I tried doing another non-inexact calculation directly after (fdenth2 = 2.0d0 * 2.0d0), but the inexact flag does\ not get reset.
0 Kudos
Steven_L_Intel1
Employee
2,439 Views
You can't - in this context, masking means preventing an exception from being raised. The only way to clear it is to execute an LDMXCSR instruction. As I indicated above, you would have to call C or assembler to do that.

Intel C++ provides intrinsics for this - let me see if I can whip up a subroutine you can call.
0 Kudos
Steven_L_Intel1
Employee
2,439 Views
Ok, this seems to do the trick. Add this interface to your subroutine and add the attached object to your build.

interface
subroutine Clear_SSE_Precision_Flag () bind(C,name="Clear_SSE_Precision_Flag")
end subroutine
end interface

The source code for the routine is this:

[cpp]#include void Clear_SSE_Precision_Flag () { unsigned int csr; csr = _mm_getcsr(); csr = csr & 0xFFFFFFDF; _mm_setcsr(csr); return; }[/cpp] Yes, I know I could probably have done this in one line. Let me know how it works for you.
0 Kudos
ferrad01
Beginner
2,439 Views
It works thanks. However the calling application is still indicating an invalid Fortran operation. It is a generic message though so I don't know which bit it is complaining about. Still looking into that.

0 Kudos
Reply