What's the equivalent of ICC -fp-model fast=2

Hello to everybody !

I'm trying to know what is the equivalent in Rust of the ICC parameter -fp-model fast=2 to enable math optimizations ?

Thank you !

rustc has some experimental intrinsics for this, e.g. std::intrinsics::fadd_fast. Or there is the fast-floats crate, which provides a newtype wrapper for f32 and f64 that overloads the usual operators (+, -, etc.) to call those intrinsics behind the scenes, in the same style as std::num::Wrapping. Either way you will have to use the nightly toolchain.

Beware that this crate exposes unsafe operations though the safe operators, and thus can be used to trigger UB in safe code. So be extremely careful while using it.

EDIT: And note that that the author of the crate is aware of this. There's a reason that it says "experiment" so many times in the crate description -- it's for trying things out, not "production-ready" code.

2 Likes

Eek, that's a good point. Seems like an extension trait with unsafe methods would be preferable then…

The fast math option(including the gcc/clang's -ffast-math and the icc's -fp-model) introduces additional UB conditions which does not comply with the IEEE-754. Just like any other UB conditions, if you step on it by mistake the compiler produces some garbage code. In Rust safe code cannot touch any UB assuming there's no bug in other unsafe code(usually written by external crates). And this makes it more complicate to use fast-math options in Rust.

I opened a PR to fast-floats adding a FastFloat extension trait with unsafe methods:

There is no standard for intensive floating-point computation ? Or do you think that using your extension-trait would be a good option ?

I know that -fp-model introduces UB, but in some cases it's usefull because you need to perform operations in less time. So for example, sqrt or powi/powf in rust could be very slow.

I'm not sure what you mean. There's no rustc flag like -fp-model to enable fast-math optimizations globally, and currently you can only get access to those operations through the unstable intrinsics or a crate like fast-floats that wraps the intrinsics.

Feel free to just copy that extension trait into your project if it's useful to you. Whether you use that approach or the fast_floats::Fast wrapper is just a matter of personal preference, they will compile to the same thing.

Yes, thank you, you are right. Just one thing, it's possible to implicit extend f32 and f64 operators (+-/*, etc) and avoid using Fast::from(val) with every number ?

No, this is not possible. But note that because of impls like this you can do

Fast(0.5_f32) + 0.5_f32

and it will still compile to a "fast" add. (Also as that shows you don't have to write Fast::from(0.5_f32), you can just do Fast(0.5_f32) since the field is pub.)

1 Like

Thank you so much !

1 Like