This is the mail archive of the
mailing list for the glibc project.
Re: [PATCH] v12 Improves __ieee754_exp() performance by 6-11% on aarch64/sparc/x86.
- From: Szabolcs Nagy <szabolcs dot nagy at arm dot com>
- To: Patrick McGehearty <patrick dot mcgehearty at oracle dot com>, libc-alpha at sourceware dot org
- Cc: nd at arm dot com
- Date: Thu, 15 Mar 2018 12:00:19 +0000
- Subject: Re: [PATCH] v12 Improves __ieee754_exp() performance by 6-11% on aarch64/sparc/x86.
- Nodisclaimer: True
- References: <email@example.com>
- Spamdiagnosticmetadata: NSPM
- Spamdiagnosticoutput: 1:99
On 15/03/18 04:22, Patrick McGehearty wrote:
New with this version:
Only updates to e_exp.c and eexp.tbl plus revised
libm-test-ulps for aarch64/sparc/x86_64 as removal of slowexp()
was accomplished by prior patch.
Summary of patch rationale
These changes will be active for all platforms that don't provide
their own exp() routines. They will also be active for ieee754
versions of ccos, ccosh, cosh, csin, csinh, sinh, exp10, gamma, and
Typical performance gains are 6% on aarch64, 28% on Sparc s7 and 11%
on x86_64 based on the glibc_perf tests.
i think this is the wrong measurement for this algorithm:
it uses two different methods for about |x|<1 and |x|>1
the first is fast (but uses yet another table) the second
is slow (!) and the branches that decide can easily
mispredict in sensible workloads.
so i think on all targets (including sparc) one could do
better by using a single method (assuming that can give
similar speed to the fast method but on the entire input
Glibc correctness tests for exp() and expf() were run. Within the test
suite 1 input value was found to cause a 1 ulp difference when
"FE_TONEAREST" rounding mode is set. No differences in exp()
were seen for the tested values for the other rounding modes.
When tested over a range of 10 million input values, the new code
gets a 1 ulp error approximately 1.6 times per 1000 values.
That rate was similar for all four rounding modes.
The patch uses a 64 entry scaling table. The existing
code uses a 512 entry table.
Further optimization is possible in the handling of rounding
modes. Using get_rounding_mode and libc_fesetround() instead of
SET_RESTORE_ROUND provides a measurable gain for Sparc.
Unfortunately, on x86, one works with sse fp unit rounding mode while
the other works on x87 fp unit rounding mode. Adding libc_fegetround,
libc_fegetroundf and libc_fegetroundl to to match libc_fesetround()
should not be too large a task but outside the scope of this patch.
the rounding mode setting should be completely removed.
(after analysis of the worst-case non-nearest rounding errors)
i think non-nearest error of this algorithm should be at most 1ulp
without rounding mode change and functions using exp may see 1-2ulp
error increase in non-nearest rounding mode (but if that's too
high that should be fixed on the call site).
but i dont want you to spend time changing the code, i'll
post my exp variant soon, so you can benchmark it on
sparc then we can continue the discussion depending on