6 ms·
Those aren't vectorized at all, just unrolled. vmulss/vaddss just multiply/add the single-precision floating-point in the vector register. With clang you get b
by camel-cdr 3y ago
Those aren't vectorized at all, just unrolled. vmulss/vaddss just multiply/add the single-precision floating-point in the vector register.
With clang you get basically the same codegen, although it uses fused multiply adds.
The problem is that you need to enable -ffast-math, otherwise the compiler can't change the order of floating point operations, and thus not vectorize.
With clang that works wonderfully and it gives us a lovely four times unrolled AVX2 fused multiply add loop, but enabling it in rust doesn't seem to work: https://godbolt.org/z/G4Enf59Kb https://godbolt.org/z/G4Enf59Kb
Edit: from what I can tell this is still an open issue??? https://github.com/rust-lang/rust/issues/21690 https://github.com/rust-lang/rust/issues/21690
Edit: relevant SO post: https://stackoverflow.com/questions/76055058/why-cant-the-rust-compiler-auto-vectorize-this-fp-dot-product-implementation https://stackoverflow.com/questions/76055058/why-cant-the-ru...
Apparently you need to use `#![feature(core_intrinsics)]`, `std::intrinsics::fadd_fast` and `std::intrinsics::fmul_fast`.
- sroussey 3y agofast-math changes even libraries not compiled with it, so buyer beware.
- steveklabnik 3y agoAhh yes, thank you. Rust doesn't have a -ffast-math flag, though it is interesting that you passed it directly to llvm. I am kinda glad that escape hatch doesn't work, to be honest. There are currently unstable intrinsics that let you do this, and you seemingly get close to clang codegen with them: https://godbolt.org/z/EEW79Gbxv https://godbolt.org/z/EEW79Gbxv The thread tracking this discusses another attempt at a flag to enable this by turning on the CPU feature directly, but that doesn't seem to affect codegen in this case. https://github.com/rust-lang/rust/issues/21690 https://github.com/rust-lang/rust/issues/21690 It would be nice to get these intrinsics stabilized, at least. EDIT: oops you figured this out while I was writing it, haha.
- cbm-vic-20 3y agoEven without a -ffast-math flag, the current stable Rust compiler will vectorize loops on integer types. https://godbolt.org/z/KjErzacfv https://godbolt.org/z/KjErzacfv Edit: ...and I now realize who I responded to, I'm sure you already know this. :)
- galangalalgol 3y agoLoops on floats are fine, its just reduction operations that hit the issue with the associativity assumption for floats leading to UB. You can trick it by making f32x16 types like the wide crate does or if you use nightly simba can do it with const generic expressions.
- nemothekid 3y agoIt was just last week I was reading a comment that made it seem like you shouldn't really use -ffast-math[0], but here looks like a non-rare reason why you would want to enable it. What is correct idiom here? It feels if this sort of thing really matters to you, you should have the know how to handroll a couple lines of ASM. I want to say this is rare, but I had a project a couple years ago where I needed to handroll some vectorized instructions on a raspberry pi. [0] https://news.ycombinator.com/item?id=39013277 https://news.ycombinator.com/item?id=39013277
- steveklabnik 3y agoThe right path forward for Rust here in my opinion is to do the same thing as is done for math operations like saturating: stabilize a function or method that performs the operation with this semantic, and then build thin wrappers on top to make using them more convenient.
- camel-cdr 3y agoImo the best solution would be special "fast" floating-point types, that have less strict requirements. I personal almost always use -ffast-math by default in my C programs that care about performance, because I almost never care enough about the loss in accuracy. The only case I remember needing it was when doing some random number distribution tests where I cared about subnormals, and got confused for a second because they didn't seem to exist (-ffast-math disables them on x86).
- lifthrasiir 3y agoThat or a scoped optimization directive. GCC does allow `__attribute__((optimize("-ffast-math")))` as a function-wide attribute, but Clang doesn't seem to have an equivalent and the standard syntax `[[gcc::optimize("-ffast-math")]]` doesn't seem to work as well. In any case, such optimization should be visible from the code in my opinion.
- lorenzored 3y agoThe problem is that it takes a single piece of code compiled with -ffast-math to break everything, it's simply not worth it