News for hackers. Stuff that matters.
Re:Improving math performance in glibc by csense on Friday January 02, 2015 @07:00PM (#8829262)
Aren't these implemented in hardware on most CPU's? Or is this floating point emulation for CPU's that don't have built-in floating point?
Re:Improving math performance in glibc by gsg on Saturday January 03, 2015 @05:25AM (#8830428)
The hardware implementations often have problems: http://randomascii.wordpress.com/2014/10/09/intel-underestim...
Re:Improving math performance in glibc by derf_ on Saturday January 03, 2015 @07:51AM (#8830645)
There's an x87 asm implementation for x86-32 in sysdeps/i386/fpu/e_exp.S [1]. For x86-64, it falls back to the generic C code for exp(), in sysdeps/ieee754/dbl-64/e_exp.c. The sad part is that there is x86-64 asm for a few variants (exp10l, exp2l, expf, expl), but since these are not C90, people tend to avoid them for more portable versions.

So, ironically, it can be orders of magnitude faster to compute a long-double expl() than a double-precision exp().

[1] Even the asm contains a lot of extra code to handle edge cases that Intel screwed up, like returning NaN for exp(+/- Inf).

Re:Improving math performance in glibc by pascal_cuoq on Saturday January 03, 2015 @08:29AM (#8830696)
The 387 instructions for elementary functions do not have the reputation of having a good accuracy/time ratio compared to, say, state-of-the-art implementations using polynomial approximations.

Do you have actual measurements that reveal some actual irony, or is it only superficial irony in that expl() is computed using the (microcoded, slow) hardware instruction and exp() isn't?

Note: For most functions, you can actually make a pretty accurate double-precision implementation by calling the corresponding 387 instruction and then rounding the result to double-precision. Not a correctly rounded implementation (that would require a wider intermediate result than 80-bit) but pretty good nonetheless.

Re:Improving math performance in glibc by derf_ on Saturday January 03, 2015 @04:19PM (#8832032)
We didn't measure average case performance, but for worst-case performance the "orders of magnitude" comment is absolutely backed by measurement. See also my comment at https://news.ycombinator.com/item?id=8830667

In our case, we only needed about 12 bits of accuracy anyway, so we wound up writing our own implementation using polynomial approximations (which have the benefit of predictable running times regardless of the quality of your C library). The fact that you need to do this in any context where worst-case performance is a concern might be surprising to some people. It was to me before I read glibc's code.

Re:Improving math performance in glibc by derf_ on Saturday January 03, 2015 @09:55PM (#8833005)
I take it back, we did measure average case performance of expf() (though not expl()), and it was slower than exp():

16:12:48 < gmaxwell> ha. So, completely eliminating all the doubles made celt slower.

16:13:23 < gmaxwell> I'm guessing that this is because I used the C99 float versions of the math functions and they suck.

16:13:57 < gmaxwell> looks like 3% slower or so.

16:14:05 < gmaxwell> <3 GLIBC.

16:26:02 < gmaxwell> with float approx the no-doubles is .9% faster. Whoohoo. ;)

17:24:06 < derf> Yes. Don't use the float versions of libc functions, at least not on x86-64.

17:24:24 < Dark_Shikari> what the heck did they do ?

17:24:53 < derf> They reset the rounding modes on entrance and exit of expf(), for example, regardless of whether or not they're already correctly set up.

17:25:07 < derf> Apparently this is really slow.

17:25:32 < gmaxwell> derf: I was hoping that they'd be fixed by now.

"Float approx" refers to our custom polynomial approximation of exp(). Given that, I think it's safe to infer that expl() would also have been slower than exp() in the average case. That was in 2010, though. This appears to have been fixed for expf() in 2012 (which now uses SSE/AVX instead of x87 asm on x86-64), but not for expl().

Re:Improving math performance in glibc by siddhesh on Sunday January 04, 2015 @11:14AM (#8834810)
> 17:24:53 < derf> They reset the rounding modes on entrance and exit of expf(), for example, regardless of whether or not they're already correctly set up.

I fixed this around the same time I worked on the mp improvements:

commit 2506109403de69bd454de27835d42e6eb6ec3abc Author: Siddhesh Poyarekar <[email protected]> Date: Wed Jun 12 10:36:48 2013 +0530

    Set/restore rounding mode only when needed
    
    The most common use case of math functions is with default rounding
    mode, i.e. rounding to nearest.  Setting and restoring rounding mode
    is an unnecessary overhead for this, so I've added support for a
    context, which does the set/restore only if the FP status needs a
    change.  The code is written such that only x86 uses these.  Other
    architectures should be unaffected by it, but would definitely benefit
    if the set/restore has as much overhead relative to the rest of the
    code, as the x86 bits do.
Re:Improving math performance in glibc by derf_ on Monday January 05, 2015 @07:45AM (#8838469)
That patch doesn't affect the x87 asm in sysdeps/x86_64/fpu/e_expl.S, though, does it? Good to hear it's fixed for some cases, though.
Re:Improving math performance in glibc by pascal_cuoq on Monday January 05, 2015 @05:13AM (#8838096)
What I meant is that the assembly instruction is faster only because it does not provide the same level of accuracy as the generic implementation.

Everyone's needs are different, but it does seem that it is a little bit early, and perhaps that it will always be too early, for a general-purpose libm to aim for correctly rounded transcendental function. Even the best implementations only work in one rounding mode, leading to the pleasantries discussed in a sibling of this comment, and the worst-case execution time can be a problem for some.

It is possible to aim for 0.51 ULP with implementations that still work(-ish) if the rounding mode is not round-to-nearest, and perhaps this is the sweet spot that libms that want to be useful should aim for.

Re:Improving math performance in glibc by CurtHagenlocher on Friday January 02, 2015 @07:06PM (#8829274)
I believe on x86/x64 CPUs there's an advantage to doing these operations via SSE rather than using the old x87 opcodes. For instance, you don't need to move data into the x87 registers.
Re:Improving math performance in glibc by Narishma on Friday January 02, 2015 @08:58PM (#8829623)
Right, you have to move it instead into the SSE registers.
Re:Improving math performance in glibc by FeepingCreature on Friday January 02, 2015 @09:49PM (#8829730)
Where it should be living anyways.