Add float16 exp/log math functions via promotion to float32 - #3228
Conversation
jan-wassenberg
left a comment
There was a problem hiding this comment.
Nice work, generally LGTM, just two quick questions.
What's the test runtime like for exhaustive enumeration? Should we also parallelize that?
|
Done in 3b32355. Added One wrinkle: the definitions are separated from the declarations, and a default template argument may not be restated, so the definitions repeat the |
|
Runtime is negligible: the full 65,536-pattern sweep is ~7 ms per function per target (~96 ms for the whole binary), so parallelizing doesn't seem worth it. The red jobs look like infra: ppc64le (Power10) failed in |
jan-wassenberg
left a comment
There was a problem hiding this comment.
Thanks for updating! A bit unfortunate about the default arg, ideally we wouldn't declare functions beforehand, but would define CallX after X(). I'll take a TODO to clean that up at some point.
Towards google#2682. Adds hwy/contrib/math/f16_math-inl.h with float16_t overloads of Exp, Exp2, Expm1, Log, Log2, Log10 and Log1p that promote to float32, evaluate the existing float32 kernels, and demote the result via DemoteTo + Combine (there is no OrderedDemote2To for f32->f16). Works on all targets, even when HWY_HAVE_FLOAT16 is 0; vectors already at HWY_MAX_POW2 (possible on RVV) take the per-half path so the float32 tag never exceeds the maximum kPow2. The new f16_math_test exhaustively sweeps all float16 bit patterns in the documented range of each function, in vector batches so that lane placement is also verified. Results are within 1 ULP of the correctly rounded float16 result (single-rounding double-precision reference; infinities must match exactly).
Per review: add HWY_IF_NOT_SPECIAL_FLOAT_D to the Exp/Exp2/Expm1/Log/ Log2/Log10/Log1p declarations (definitions repeat the EnableIf without the default argument, which may not be restated), so the float16 overloads can use HWY_IF_F16_D instead of relying on partial ordering of Simd<float16_t, N, kPow2>.
|
Internal CI is failing on Arm: Please update the ulp tolerance to 2 :) |
Internal CI reported Exp(-13.882812) off by 2 ULP on Arm. The result there is 9.3e-07, a float16 subnormal: spacing is a fixed 2^-24, so the smallest results hold only about four significant bits and a float32 result that differs slightly between targets lands two float16 values away. Exp, Exp2, Expm1 and Log1p are the functions whose results reach the subnormals, so all four now allow 2 ULP; the logarithms never return a subnormal and stay at 1.
jan-wassenberg
left a comment
There was a problem hiding this comment.
Thanks for updating :)
Towards #2682 — first PR of the series discussed there: adds
float16_toverloads ofExp,Exp2,Expm1,Log,Log2,Log10andLog1pin a newhwy/contrib/math/f16_math-inl.h, which promote to float32, evaluate the existing float32 kernels, and demote the result viaDemoteTo+Combineas suggested (noOrderedDemote2Tofor f32->f16).Notes:
Simd<float16_t, N, kPow2>so they are more specialized than the unconstrained templates in math-inl.h; a SFINAE-constrained overload with the same signature would be ambiguous. No changes to math-inl.h are needed.HWY_HAVE_FLOAT16is 0 — only ops from the always-supported list in quick_reference.md are used. Vectors that fit in half of the widest vector use a single promotion; wider vectors (and RVV tags already atHWY_MAX_POW2, whereRebindto float would be illegal) take a per-half path.f16_math_testexhaustively tests all float16 bit patterns in each function's documented range, in vector batches so that lane placement is also verified. Max observed error is 1 ULP against a single-rounded double-precision reference, with infinities required to match exactly.Follow-up PRs will add the remaining functions in batches, with
Hypotand other special cases last.