3 ms·
-ffast-math quickly loses its value once you start dispatching raw intrinsics. -ffast-math tells the compiler "just figure or the math for me, I know what I wan
by nwallin 7y ago
-ffast-math quickly loses its value once you start dispatching raw intrinsics. -ffast-math tells the compiler "just figure or the math for me, I know what I want but don't know how to get it", but raw intrinsics say "use this instruction, but deal with manual register management for me."
If you take the code `v /= v.length();` and given -ffast-math the compiler can easily compile that as a mul, two fmas, an rsqrt, and three muls.
But if you take the code: (can't format right on mobile) (edit: fixed on desktop)
__m256 len = _mm256_mul_ps(v.x, v.x);
len = _mm256_add_ps(len, _mm256_mul_ps(v.y,v.y));
len = _mm256_add_ps(len, _mm256_mul(v.z,v.z));
len = _mm256_sqrt_ps(len);
v.x = _mm256_div_ps(v.x, len);
v.y = _mm256_div_ps(v.y, len);
v.z = _mm256_div_ps(v.z, len);
You've told the compiler exactly which instructions to execute. And it will do so faithfully even though it's like two orders of magnitude slower.
I would be very interested to see -Ofast used before SIMD intrinsics start getting thrown around, but it has no value afterwards. The code in the linked article is eventually almost all SIMD intrinsics (v4?) so it won't make a difference.
- mkbosmans 7y agoWhat are you talking about? Intrinsics don't force the compiler to use a specific instruction. It's not even a 1:1 mapping. I think all compilers will fuse separate add and mul instrinsics to fmadd. Both GCC and Clang will convert the _mm256_div_ps to a vmulps. GCC calculates the scaling factor by combining vsqrtps and vrcpps. Clang will emit a vrsqrtps instruction, but as that has only 12 bits of guaranteed accuracy, it fixes the result up before using it to scale x, y and z. https://godbolt.org/z/rG2rH8 https://godbolt.org/z/rG2rH8