Quantcast

math:exp() erlang bug on SPARC

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

math:exp() erlang bug on SPARC

Matt Keenan
Hi,

Just wanted to report a SPARC specific issue with Erlang.

See discussions:
   https://github.com/rabbitmq/rabbitmq-server/issues/132
   https://groups.google.com/forum/#!topic/rabbitmq-users/Gca8vW52gB8

Only happens on SPARC systems does not occur on X86 architecture.
e.g.:

On s11u3 x86:
1> math:exp(-1162.102134881488).
0.0

On s11u3 SPARC:
1> math:exp(-1162.102134881488).
** exception error: an error occurred when evaluating an arithmetic
expression in function math:exp/1 called as math:exp(-1162.102134881488)

Both systems are running 64-bit Erlang 17.5 in a 64-bit environment.

Has an issue related to this been posted before ?

cheers

Matt
_______________________________________________
erlang-bugs mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-bugs
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: math:exp() erlang bug on SPARC

Jesper Louis Andersen-2

On Wed, Apr 13, 2016 at 3:46 PM, Matt Keenan <[hidden email]> wrote:
Just wanted to report a SPARC specific issue with Erlang.

I'm not entirely convinced it is with Erlang, so consider this inquiry. Sparc uses a 64bit wide internal representation of IEEE 754 double binary fp numbers, whereas the internal representation in x86 is 80 bit wide (due to that being the width of the 387 coprocessor back in the day).

exp(-1162.102134881488)

is 2.02048... x 10^-505 which is smaller than the smallest representable float. The limit, as x -> -infty is 0 for exp(_), so one would argue that the correct output in this case is 0.0.

Erlang simply calls into the C math.h exp function for this, but it does FP exception checks around the point. One way to figure out what happens would be to get hold of a SPARC machine, write a simple C program doing the same and verifying that the SPARC compilers agrees on that one with an x86 program. I could imagine some way it provokes an FP exception on the SPARC architecture, but not on x86 due to the extra bits x86 has in internal encoding width.

--
J.

_______________________________________________
erlang-bugs mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-bugs
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: math:exp() erlang bug on SPARC

Ben Murphy-2
I think the issue is with Solaris implementation of exp in libm (i
don't know if it is actually correct or not....):

You can take the code exp.c code from illumos (opensolaris fork)
https://github.com/joyent/illumos-joyent/blob/master/usr/src/lib/libm/common/C/exp.c#L334
and run it on x86 and you will see the same issue. It falls over on:
if (-x > threshold2)

So if you do exp(x) and x < -7.45133219101941108420e+02 then you trigger it


On Thu, Apr 14, 2016 at 12:24 PM, Jesper Louis Andersen
<[hidden email]> wrote:

>
> On Wed, Apr 13, 2016 at 3:46 PM, Matt Keenan <[hidden email]> wrote:
>>
>> Just wanted to report a SPARC specific issue with Erlang.
>
>
> I'm not entirely convinced it is with Erlang, so consider this inquiry.
> Sparc uses a 64bit wide internal representation of IEEE 754 double binary fp
> numbers, whereas the internal representation in x86 is 80 bit wide (due to
> that being the width of the 387 coprocessor back in the day).
>
> exp(-1162.102134881488)
>
> is 2.02048... x 10^-505 which is smaller than the smallest representable
> float. The limit, as x -> -infty is 0 for exp(_), so one would argue that
> the correct output in this case is 0.0.
>
> Erlang simply calls into the C math.h exp function for this, but it does FP
> exception checks around the point. One way to figure out what happens would
> be to get hold of a SPARC machine, write a simple C program doing the same
> and verifying that the SPARC compilers agrees on that one with an x86
> program. I could imagine some way it provokes an FP exception on the SPARC
> architecture, but not on x86 due to the extra bits x86 has in internal
> encoding width.
>
> --
> J.
>
> _______________________________________________
> erlang-bugs mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-bugs
>
_______________________________________________
erlang-bugs mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-bugs
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: math:exp() erlang bug on SPARC

Mikael Pettersson-5
In reply to this post by Matt Keenan
Matt Keenan writes:
 > Hi,
 >
 > Just wanted to report a SPARC specific issue with Erlang.
 >
 > See discussions:
 >    https://github.com/rabbitmq/rabbitmq-server/issues/132
 >    https://groups.google.com/forum/#!topic/rabbitmq-users/Gca8vW52gB8
 >
 > Only happens on SPARC systems does not occur on X86 architecture.
 > e.g.:
 >
 > On s11u3 x86:
 > 1> math:exp(-1162.102134881488).
 > 0.0
 >
 > On s11u3 SPARC:
 > 1> math:exp(-1162.102134881488).
 > ** exception error: an error occurred when evaluating an arithmetic
 > expression in function math:exp/1 called as math:exp(-1162.102134881488)
 >
 > Both systems are running 64-bit Erlang 17.5 in a 64-bit environment.
 >
 > Has an issue related to this been posted before ?

After reproducing this on Solaris 10 / SPARC I recalled:
http://erlang.org/pipermail/erlang-bugs/2014-December/004731.html

First, this call to exp(-1162.1...) goes straight to libm's exp(), which
detects an underflow and returns an error on both Solaris (SPARC) and Linux
(x86_64, sparc64, ARMv7) [all glibc].  In this case, exp() returns 0,
sets errno, and sets flag bits testable by fetestexcept().

On Solaris, libm also calls matherr() as per ancient SVID, and ERTS treats
that as an implicit FP exception.

After exp() returns, ERTS checks (1) if the return value is !isfinite()
[but here it's a finite 0], or (2) if the thread's FP exception flag is set.
On Solaris it's set due to the matherr() call, so the call is treated as
an error.  On Linux we see a finite return value, don't check the error
indicators, and go on as if no error occurred.  (That may be correct for
underflow errors, I don't know.)

The older email thread was about a similar issue with math:pow/2.

Our treatment of matherr() is completely wrong.  With FP exceptions disabled,
we derive no information from matherr() calls, so all error checking is
expressed in the code around those libm calls.  For libm calls, checking for
real FP exceptions is needed to reset parts of the FPU controls, but that
isn't needed for the fake FP exceptions derived from matherr() calls.

In short, I think matherr() should be a no-op regardless of NO_FPE_SIGNALS.

The path below should fix your issue on Solaris.  I'll issue a PR later.

/Mikael

diff --git a/erts/emulator/sys/ose/sys_float.c b/erts/emulator/sys/ose/sys_float.c
index 5187579..764c35b 100644
--- a/erts/emulator/sys/ose/sys_float.c
+++ b/erts/emulator/sys/ose/sys_float.c
@@ -836,10 +836,5 @@ sys_chars_to_double(char* buf, double* fp)
 int
 matherr(struct exception *exc)
 {
-#if !defined(NO_FPE_SIGNALS)
-    volatile unsigned long *fpexnp = erts_get_current_fp_exception();
-    if (fpexnp != NULL)
- *fpexnp = (unsigned long)__builtin_return_address(0);
-#endif
     return 1;
 }
diff --git a/erts/emulator/sys/unix/sys_float.c b/erts/emulator/sys/unix/sys_float.c
index 8fe7e59..beb5cb5 100644
--- a/erts/emulator/sys/unix/sys_float.c
+++ b/erts/emulator/sys/unix/sys_float.c
@@ -838,11 +838,6 @@ sys_chars_to_double(char* buf, double* fp)
 int
 matherr(struct exception *exc)
 {
-#if !defined(NO_FPE_SIGNALS)
-    volatile unsigned long *fpexnp = erts_get_current_fp_exception();
-    if (fpexnp != NULL)
- *fpexnp = (unsigned long)__builtin_return_address(0);
-#endif
     return 1;
 }
 
diff --git a/erts/emulator/sys/win32/sys_float.c b/erts/emulator/sys/win32/sys_float.c
index 86e822d..14d4fa0 100644
--- a/erts/emulator/sys/win32/sys_float.c
+++ b/erts/emulator/sys/win32/sys_float.c
@@ -139,8 +139,7 @@ sys_double_to_chars_ext(double fp, char *buffer, size_t buffer_size, size_t deci
 int
 matherr(struct _exception *exc)
 {
-    erl_fp_exception = 1;
-    DEBUGF(("FP exception (matherr) (0x%x) (%d)\n", exc->type, erl_fp_exception));
+    DEBUGF(("FP exception (matherr) (0x%x)\n", exc->type));
     return 1;
 }
 
_______________________________________________
erlang-bugs mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-bugs
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: math:exp() erlang bug on SPARC

Matt Keenan
Mikael,

This is great, I'll attempt applying your code changes below on a local
Solaris build of Erlang and verify if it fixes the issue for me.

thanks

Matt

On 16/04/2016 20:12, Mikael Pettersson wrote:

> Matt Keenan writes:
>   > Hi,
>   >
>   > Just wanted to report a SPARC specific issue with Erlang.
>   >
>   > See discussions:
>   >    https://github.com/rabbitmq/rabbitmq-server/issues/132
>   >    https://groups.google.com/forum/#!topic/rabbitmq-users/Gca8vW52gB8
>   >
>   > Only happens on SPARC systems does not occur on X86 architecture.
>   > e.g.:
>   >
>   > On s11u3 x86:
>   > 1> math:exp(-1162.102134881488).
>   > 0.0
>   >
>   > On s11u3 SPARC:
>   > 1> math:exp(-1162.102134881488).
>   > ** exception error: an error occurred when evaluating an arithmetic
>   > expression in function math:exp/1 called as math:exp(-1162.102134881488)
>   >
>   > Both systems are running 64-bit Erlang 17.5 in a 64-bit environment.
>   >
>   > Has an issue related to this been posted before ?
>
> After reproducing this on Solaris 10 / SPARC I recalled:
> http://erlang.org/pipermail/erlang-bugs/2014-December/004731.html
>
> First, this call to exp(-1162.1...) goes straight to libm's exp(), which
> detects an underflow and returns an error on both Solaris (SPARC) and Linux
> (x86_64, sparc64, ARMv7) [all glibc].  In this case, exp() returns 0,
> sets errno, and sets flag bits testable by fetestexcept().
>
> On Solaris, libm also calls matherr() as per ancient SVID, and ERTS treats
> that as an implicit FP exception.
>
> After exp() returns, ERTS checks (1) if the return value is !isfinite()
> [but here it's a finite 0], or (2) if the thread's FP exception flag is set.
> On Solaris it's set due to the matherr() call, so the call is treated as
> an error.  On Linux we see a finite return value, don't check the error
> indicators, and go on as if no error occurred.  (That may be correct for
> underflow errors, I don't know.)
>
> The older email thread was about a similar issue with math:pow/2.
>
> Our treatment of matherr() is completely wrong.  With FP exceptions disabled,
> we derive no information from matherr() calls, so all error checking is
> expressed in the code around those libm calls.  For libm calls, checking for
> real FP exceptions is needed to reset parts of the FPU controls, but that
> isn't needed for the fake FP exceptions derived from matherr() calls.
>
> In short, I think matherr() should be a no-op regardless of NO_FPE_SIGNALS.
>
> The path below should fix your issue on Solaris.  I'll issue a PR later.
>
> /Mikael
>
> diff --git a/erts/emulator/sys/ose/sys_float.c b/erts/emulator/sys/ose/sys_float.c
> index 5187579..764c35b 100644
> --- a/erts/emulator/sys/ose/sys_float.c
> +++ b/erts/emulator/sys/ose/sys_float.c
> @@ -836,10 +836,5 @@ sys_chars_to_double(char* buf, double* fp)
>   int
>   matherr(struct exception *exc)
>   {
> -#if !defined(NO_FPE_SIGNALS)
> -    volatile unsigned long *fpexnp = erts_get_current_fp_exception();
> -    if (fpexnp != NULL)
> - *fpexnp = (unsigned long)__builtin_return_address(0);
> -#endif
>       return 1;
>   }
> diff --git a/erts/emulator/sys/unix/sys_float.c b/erts/emulator/sys/unix/sys_float.c
> index 8fe7e59..beb5cb5 100644
> --- a/erts/emulator/sys/unix/sys_float.c
> +++ b/erts/emulator/sys/unix/sys_float.c
> @@ -838,11 +838,6 @@ sys_chars_to_double(char* buf, double* fp)
>   int
>   matherr(struct exception *exc)
>   {
> -#if !defined(NO_FPE_SIGNALS)
> -    volatile unsigned long *fpexnp = erts_get_current_fp_exception();
> -    if (fpexnp != NULL)
> - *fpexnp = (unsigned long)__builtin_return_address(0);
> -#endif
>       return 1;
>   }
>
> diff --git a/erts/emulator/sys/win32/sys_float.c b/erts/emulator/sys/win32/sys_float.c
> index 86e822d..14d4fa0 100644
> --- a/erts/emulator/sys/win32/sys_float.c
> +++ b/erts/emulator/sys/win32/sys_float.c
> @@ -139,8 +139,7 @@ sys_double_to_chars_ext(double fp, char *buffer, size_t buffer_size, size_t deci
>   int
>   matherr(struct _exception *exc)
>   {
> -    erl_fp_exception = 1;
> -    DEBUGF(("FP exception (matherr) (0x%x) (%d)\n", exc->type, erl_fp_exception));
> +    DEBUGF(("FP exception (matherr) (0x%x)\n", exc->type));
>       return 1;
>   }
>
>

_______________________________________________
erlang-bugs mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-bugs
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: math:exp() erlang bug on SPARC

Matt Keenan
In reply to this post by Mikael Pettersson-5
Hi Mikael,

Just wanted to confirm that your recommended patch below works on my
Local SPARC box.

thanks

Matt

On 04/16/16 20:12, Mikael Pettersson wrote:

> Matt Keenan writes:
>   > Hi,
>   >
>   > Just wanted to report a SPARC specific issue with Erlang.
>   >
>   > See discussions:
>   >    https://github.com/rabbitmq/rabbitmq-server/issues/132
>   >    https://groups.google.com/forum/#!topic/rabbitmq-users/Gca8vW52gB8
>   >
>   > Only happens on SPARC systems does not occur on X86 architecture.
>   > e.g.:
>   >
>   > On s11u3 x86:
>   > 1> math:exp(-1162.102134881488).
>   > 0.0
>   >
>   > On s11u3 SPARC:
>   > 1> math:exp(-1162.102134881488).
>   > ** exception error: an error occurred when evaluating an arithmetic
>   > expression in function math:exp/1 called as math:exp(-1162.102134881488)
>   >
>   > Both systems are running 64-bit Erlang 17.5 in a 64-bit environment.
>   >
>   > Has an issue related to this been posted before ?
>
> After reproducing this on Solaris 10 / SPARC I recalled:
> http://erlang.org/pipermail/erlang-bugs/2014-December/004731.html
>
> First, this call to exp(-1162.1...) goes straight to libm's exp(), which
> detects an underflow and returns an error on both Solaris (SPARC) and Linux
> (x86_64, sparc64, ARMv7) [all glibc].  In this case, exp() returns 0,
> sets errno, and sets flag bits testable by fetestexcept().
>
> On Solaris, libm also calls matherr() as per ancient SVID, and ERTS treats
> that as an implicit FP exception.
>
> After exp() returns, ERTS checks (1) if the return value is !isfinite()
> [but here it's a finite 0], or (2) if the thread's FP exception flag is set.
> On Solaris it's set due to the matherr() call, so the call is treated as
> an error.  On Linux we see a finite return value, don't check the error
> indicators, and go on as if no error occurred.  (That may be correct for
> underflow errors, I don't know.)
>
> The older email thread was about a similar issue with math:pow/2.
>
> Our treatment of matherr() is completely wrong.  With FP exceptions disabled,
> we derive no information from matherr() calls, so all error checking is
> expressed in the code around those libm calls.  For libm calls, checking for
> real FP exceptions is needed to reset parts of the FPU controls, but that
> isn't needed for the fake FP exceptions derived from matherr() calls.
>
> In short, I think matherr() should be a no-op regardless of NO_FPE_SIGNALS.
>
> The path below should fix your issue on Solaris.  I'll issue a PR later.
>
> /Mikael
>
> diff --git a/erts/emulator/sys/ose/sys_float.c b/erts/emulator/sys/ose/sys_float.c
> index 5187579..764c35b 100644
> --- a/erts/emulator/sys/ose/sys_float.c
> +++ b/erts/emulator/sys/ose/sys_float.c
> @@ -836,10 +836,5 @@ sys_chars_to_double(char* buf, double* fp)
>   int
>   matherr(struct exception *exc)
>   {
> -#if !defined(NO_FPE_SIGNALS)
> -    volatile unsigned long *fpexnp = erts_get_current_fp_exception();
> -    if (fpexnp != NULL)
> - *fpexnp = (unsigned long)__builtin_return_address(0);
> -#endif
>       return 1;
>   }
> diff --git a/erts/emulator/sys/unix/sys_float.c b/erts/emulator/sys/unix/sys_float.c
> index 8fe7e59..beb5cb5 100644
> --- a/erts/emulator/sys/unix/sys_float.c
> +++ b/erts/emulator/sys/unix/sys_float.c
> @@ -838,11 +838,6 @@ sys_chars_to_double(char* buf, double* fp)
>   int
>   matherr(struct exception *exc)
>   {
> -#if !defined(NO_FPE_SIGNALS)
> -    volatile unsigned long *fpexnp = erts_get_current_fp_exception();
> -    if (fpexnp != NULL)
> - *fpexnp = (unsigned long)__builtin_return_address(0);
> -#endif
>       return 1;
>   }
>
> diff --git a/erts/emulator/sys/win32/sys_float.c b/erts/emulator/sys/win32/sys_float.c
> index 86e822d..14d4fa0 100644
> --- a/erts/emulator/sys/win32/sys_float.c
> +++ b/erts/emulator/sys/win32/sys_float.c
> @@ -139,8 +139,7 @@ sys_double_to_chars_ext(double fp, char *buffer, size_t buffer_size, size_t deci
>   int
>   matherr(struct _exception *exc)
>   {
> -    erl_fp_exception = 1;
> -    DEBUGF(("FP exception (matherr) (0x%x) (%d)\n", exc->type, erl_fp_exception));
> +    DEBUGF(("FP exception (matherr) (0x%x)\n", exc->type));
>       return 1;
>   }
>
>

_______________________________________________
erlang-bugs mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-bugs
Loading...