Add workaround for using std::fma for scalar multiply-add.

This commit is contained in:
Antonio Sánchez
2025-10-09 18:57:46 +00:00
committed by Rasmus Munk Larsen
parent 5996176b88
commit ef3c5c1d1d
3 changed files with 25 additions and 10 deletions

View File

@@ -1004,8 +1004,7 @@ struct madd_impl {
}
};
// Use FMA if there is a single CPU instruction.
#ifdef EIGEN_VECTORIZE_FMA
#if EIGEN_SCALAR_MADD_USE_FMA
template <typename Scalar>
struct madd_impl<Scalar, std::enable_if_t<has_fma<Scalar>::value>> {
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run(const Scalar& x, const Scalar& y, const Scalar& z) {
@@ -1927,7 +1926,6 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar arithmetic_shift_right(const Scalar
return bit_cast<Scalar, SignedScalar>(bit_cast<SignedScalar, Scalar>(a) >> n);
}
// Otherwise, rely on template implementation.
template <typename Scalar>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar fma(const Scalar& x, const Scalar& y, const Scalar& z) {
return internal::fma_impl<Scalar>::run(x, y, z);

View File

@@ -52,6 +52,26 @@
#define EIGEN_STACK_ALLOCATION_LIMIT 131072
#endif
/* Specify whether to use std::fma for scalar multiply-add instructions.
*
* On machines that have FMA as a single instruction, this will generally
* improve precision without significant performance implications.
*
* Without a single instruction, performance has been found to be reduced 2-3x
* on Intel CPUs, and up to 30x for WASM.
*
* If unspecified, defaults to using FMA if hardware support is available.
* The default should be used in most cases to ensure consistency between
* vectorized and non-vectorized paths.
*/
#ifndef EIGEN_SCALAR_MADD_USE_FMA
#ifdef EIGEN_VECTORIZE_FMA
#define EIGEN_SCALAR_MADD_USE_FMA 1
#else
#define EIGEN_SCALAR_MADD_USE_FMA 0
#endif
#endif
//------------------------------------------------------------------------------------------
// Compiler identification, EIGEN_COMP_*
//------------------------------------------------------------------------------------------