Live data from Hacker News

Std: Clamp generates less efficient assembly than std:min(max,std:max(min,v))

1f6042.blogspot.com

61–70 of 152 posts

Re: Std: Clamp generates less efficient assembly than std:min(max,std:max(min,v))

#61
post #59
post #47

Earlier quoted context omitted.

You can't fully disable fast-math per-library, moreover a library compiled with fast-math might also introduce inaccuracies in a seemingly unrelated library or application code in the same executable. The reason is that fast-math enables some dynamic initialization of the library that changes the floating point environment in some ways.

> You can’t fully disable fast-math per library Can you elaborate? What fast-math can sneak into a library that disabled fast-math at compile time? > fast-math enables some dynamic initialization of the library that changes the floating point environment in some ways. I wasn’t aware of this, I would love to see some documentation discussing exactly what happens, can you send a link?

> Can you elaborate? What fast-math can sneak into a library that disabled fast-math at compile time?

A lot of library code is in headers (especially in C++!). The code in headers is compiled by your compiler using your compile options.

Re: Std: Clamp generates less efficient assembly than std:min(max,std:max(min,v))

#62
post #37

Earlier quoted context omitted.

Why do you say almost never? Don’t let the name scare you; all floating point math is inaccurate. Fast math is only slightly less accurate, I think typically it’s a 1 or maybe 2 LSB difference. At least in CUDA it is, and I think many (most?) people & situations can tolerate 22 bits of mantissa compared to 23, and many (most?) people/situations aren’t paying attention to inf/nan/exception issues at all. I deal with a…

> Fast math is only slightly less accurate 'slightly'? Last I checked, -Ofast completely breaks std::isnan and std::isinf--they always return false.

Hopefully it was clear from the rest of my comment that I was talking about in-range floats there. I wouldn’t necessarily call inf & nan handling an accuracy issue, that’s more about exceptional cases, but to your point I would have to agree that losing std::isinf is kinda bad since divide by zero is probably near the very top of the list of things most people using floats casually might have to deal with.

Which compiler are you using where std::isinf breaks? Hopefully it was also clear that my experience leans toward CUDA, and I think the inf & nan support works there in the presence of NVCC’s fast-math.

Re: Std: Clamp generates less efficient assembly than std:min(max,std:max(min,v))

#63
post #61
post #59

Earlier quoted context omitted.

> You can’t fully disable fast-math per library Can you elaborate? What fast-math can sneak into a library that disabled fast-math at compile time? > fast-math enables some dynamic initialization of the library that changes the floating point environment in some ways. I wasn’t aware of this, I would love to see some documentation discussing exactly what happens, can you send a link?

> Can you elaborate? What fast-math can sneak into a library that disabled fast-math at compile time? A lot of library code is in headers (especially in C++!). The code in headers is compiled by your compiler using your compile options.

Ah, of course, very good point. A header-only library doesn’t have separate compile options. This is a great reason for a float-sensitive library to not be header-only, right?

Re: Std: Clamp generates less efficient assembly than std:min(max,std:max(min,v))

#64
post #63
post #61

Earlier quoted context omitted.

> Can you elaborate? What fast-math can sneak into a library that disabled fast-math at compile time? A lot of library code is in headers (especially in C++!). The code in headers is compiled by your compiler using your compile options.

Ah, of course, very good point. A header-only library doesn’t have separate compile options. This is a great reason for a float-sensitive library to not be header-only, right?

It's not just about being header-only, lots of libraries which aren't header-only still have code in headers. The library may choose to put certain functions in headers for performance reasons (to let compiler inline them), or, in C++, function templates and class templates generally have to be in headers.

But yeah, it's probably a good idea to not put code which breaks under -ffast-math in headers if possible.

Re: Std: Clamp generates less efficient assembly than std:min(max,std:max(min,v))

#65
post #37
post #11

Earlier quoted context omitted.

You (celegans25) probably know this but here is a PSA that -ffast-math is really -finaccurate-math. The knowledgeable developer will know when to use it (almost never) while the naive user will have bugs.

Why do you say almost never? Don’t let the name scare you; all floating point math is inaccurate. Fast math is only slightly less accurate, I think typically it’s a 1 or maybe 2 LSB difference. At least in CUDA it is, and I think many (most?) people & situations can tolerate 22 bits of mantissa compared to 23, and many (most?) people/situations aren’t paying attention to inf/nan/exception issues at all. I deal with a…

Here are some of the problems with fast-math:

* It links in an object file that enables denormal flushing globally, so that it affects all libraries linked into your application, even if said library explicitly doesn't want fast-math. This is seriously one of the most user-hostile things a compiler can do.

* The results of your program will vary depending on the exact make of your compiler and other random attributes of your compile environment, which can wreak havoc if you have code that absolutely wants bit-identical results. This doesn't matter for everybody, but there are some domains where this can be a non-starter (e.g., multiplayer game code).

* Fast-math precludes you from being able to use NaN or infinities, and often even being able to defensively test for NaN or infinity. Sure, there are times where this is useful, but an option you might generally prefer to suggest for an uninformed programmer would rather be a "floating-point code can't overflow" option rather than "infinity doesn't exist and it's UB if it does exist".

* Fast-math can cause hard range guarantees to fail. Maybe you've got code that you can prove that, even with rounding error, the result will still be >= 0. With fast-math, the code might be adjusted so that the result is instead, say, -1e-10. And if you pass that to a function with a hard domain error at 0 (like sqrt), you now go from the result being 0 to the result being NaN. And see above about what happens when you get NaN.

Fast-math is a tradeoff, and if you're willing to except the tradeoff it offers, it's a fine option to use. But most programmers don't even know what the tradeoffs are, and the failure mode can be absolutely catastrophic. It's definitely an option that is in the "you must be this knowledgeable to use" camp.

Re: Std: Clamp generates less efficient assembly than std:min(max,std:max(min,v))

#66
post #60
post #45

Earlier quoted context omitted.

It shouldn’t be scary. Any library that is sensitive to order of operations will hopefully have a big fat warning on it. And it can be compiled separately with fast-math disabled. I don’t know of any such libraries off the top of my head, and it’s quite rare to find situations that result in orders of magnitude more error, though I grant you it can happen, and it can be contrived pretty easily.

I don't typically thoroughly read through the documentation for all the dependencies which my dependencies are using. But you're correct that it's probably usually fine in practice.

That’s fair. Ideally transitive dependencies should be completely hidden from you. Hopefully the author of the library you include directly has heeded the instructions of libraries they depend on.

Hey I grant and acknowledge that using fast-math carries a little risk of surprises, we don’t necessarily need to try to think of corner cases. I’m mostly pushing back a little because using floats at all carries almost as much risk. A lot of people seem to use floats without knowing how inaccurate floats are, and a lot of people aren’t doing precision analysis or handling the exceptional cases… and don’t really need to.

Re: Std: Clamp generates less efficient assembly than std:min(max,std:max(min,v))

#67
post #41
post #11

Earlier quoted context omitted.

You (celegans25) probably know this but here is a PSA that -ffast-math is really -finaccurate-math. The knowledgeable developer will know when to use it (almost never) while the naive user will have bugs.

What you really should enable is the fun and safe math optimizations, with -funsafe-math-optimizations.

I know almost nothing about compiler flags but I got a laugh out of this even though I still don't know if you're joking or not. Edit: Just read it again and now I understand the joke. Haha

Re: Std: Clamp generates less efficient assembly than std:min(max,std:max(min,v))

#68
post #56

Earlier quoted context omitted.

-Ofast is one of those dangerous flags that you should probably be careful with. It is “contagious” and it can mess up code elsewhere in the program, because it changes processor flags. I would try a more specific flag like -ffinite-math-only.

finite-math-only is a footgun as well as it allows the compiler assume that NaNs do not exist. Which means all `isnan()` calls are just reduced to `false` so it’s difficult to program defensively. And if a NaN in fact occurs it’s naturally a one-way ticket to UB land.

If that’s a foot gun, then -Ofast is an autocannon.

I like to think that the flag should be renamed “-Ofuck-my-shit-up”.

Re: Std: Clamp generates less efficient assembly than std:min(max,std:max(min,v))

#69

On gcc 13, the difference in assembly between the min(max()) version and std::clamp is eliminated when I add the -ffast-math flag. I suspect that the two implementations handle one of the arguments being NaN a bit differently. https://gcc.godbolt.org/z/fGaP6roe9 I see the same behavior on clang 17 as well https://gcc.godbolt.org/z/6jvnoxWhb

[deleted]

Re: Std: Clamp generates less efficient assembly than std:min(max,std:max(min,v))

#70
post #47
post #45

Earlier quoted context omitted.

It shouldn’t be scary. Any library that is sensitive to order of operations will hopefully have a big fat warning on it. And it can be compiled separately with fast-math disabled. I don’t know of any such libraries off the top of my head, and it’s quite rare to find situations that result in orders of magnitude more error, though I grant you it can happen, and it can be contrived pretty easily.

You can't fully disable fast-math per-library, moreover a library compiled with fast-math might also introduce inaccuracies in a seemingly unrelated library or application code in the same executable. The reason is that fast-math enables some dynamic initialization of the library that changes the floating point environment in some ways.

[deleted]
Post reply on HN