- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
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.
Link Copied
5 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
I tried doing another non-inexact calculation directly after (fdenth2 = 2.0d0 * 2.0d0), but the inexact flag does\ not get reset.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Intel C++ provides intrinsics for this - let me see if I can whip up a subroutine you can call.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page