PV_MagSmooth formula efficiency question

C people – in this expression (from MCLDFFTUGens - MagSmooth) – is the struct access more costly, or the multiplication?

// float onemfactor = 1.f - factor

memory[i] = p->bin[i].mag = (memory[i] * factor) + (p->bin[i].mag * onemfactor);

That is, an equivalent calculation would be:

memory[i] = p->bin[i].mag = (memory[i] - p->bin[i].mag) * factor + p->bin[i].mag;

So,

  • Old way: One +, two *, two array accesses
  • New way: Two +/-, one *, 3 array accesses

If not for the extra array access, I’d move to the version with fewer *. But maybe with SIMD, it’s faster to avoid the extra memory access? Or the compiler will optimize out the double access to p[i]->bin.mag?

(I’m experimenting to see what it sounds like if it smooths phase as well.)

hjh

Yes. The compiler knows that p[i]->bin can’t possibly change during the expression, so it will certainly coalesce the two loads.

Cool, maybe worth a tiny PR then (since two adds and a multiply should be cheaper than two multiplies and an add).

hjh

Since this topic is about compiler optimizations, I thought I should add one more thing:

By default, the compiler cannot freely transform floating point expressions because floating point operations are not really associative. You need to tell the compiler that you don’t care about the source order. With GCC/Clang you can build with -ffast-math, with MSVC you can use /fp:fast. Note that with both options the compiler pretends that NaNs don’t exist, so this would break any code that relies on the existence of NaNs. (Some SC plugins do!) In this case, you can do -ffast-math -fno-finite-math-only. Alternatively, you may list all the “unsafe” math operations you’re interested in. E.g. SuperCollider is built with

-fno-math-errno          # Optimize math functions by not setting errno
-fno-signaling-nans      # Assume no signaling NaNs for better optimization
-fsigned-zeros           # Maintain distinction between -0.0 and +0.0
-fno-associative-math    # Prevent reordering of floating-point operations

See also FloatingPointMath - GCC Wiki.

Unfortunately, MSVC does not give you this level of control. If you want the compiler to perform arbitrary transformations of floating point expressions while your code depends on the existance of NaNs, you are out of luck. At least, Visual Studio 2022 added /fp:contract which enables floating point contractions (e.g. fused-multiply-add). See /fp (Specify floating-point behavior) | Microsoft Learn

1 Like