-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Should SIMD add/sub/etc. trigger panics on overflow in debug mode? #56
Comments
I don't think so. First of all a technical question: can rust code even cfg on overflow-checks being true or false? Second: even if we could, we should not. it would make the debug code unacceptably slow. rust has a lot of things that make for slow debug code and long compiles in release, we should not compound the problem if we don't have to. |
I do tend to agree that maybe SIMD should default to wrapping implementations (but provide checked member fns as well). I would have left |
I do not believe so.
In the spirit of sounding out the alternatives (or at least warming up our counterarguments for when someone inevitably asks), I must note that scalar math triggers panics on overflows in debug mode. Why should this not be consistent? Yes, it is slower, but what special need is there to speed this up in debug mode versus any special need in scalar math? |
"because you only pick simd in the first place if you want to go faster" but I'm quite biased. I've never ever wanted checked in debug wrapping in release anyway. it was a bad decision then, we shouldn't double down on it now. |
I think I agree, the only reason to use SIMD is for performance, so the default should probably be the most performant. I tend to agree that wrapping would probably have been the better default. When safety is involved I use |
I don't agree with this, but I agree with the broad sentiment that it doesn't make sense for SIMD. |
I do think it's worth pointing out that there are generic bit tricks you can do to produce relatively performant "any of" mask checks (and special instructions like movemask on some architectures). The branch will really be what hurts, though, and that's unavoidable. |
I think a bigger issue is that it encourages some sort of manual checking at various points which is awkward and usually unnecessary. I'm not concerned about debug performance here, short of wanting to avoid the debug performance issues of core::arch where nothing is inlined and you typically loose a ton of debug perf when switching from scalar to simd. |
I would also note that if you are doing one math, you are likely to do another math, as it were, in SIMD, whereas ordinary math ops are much more likely to appear isolatively, and it is correct to note that any such guard should probably not be in the middle of the code! Also, SIMD ops being much more likely to come one after the other means that any branching in debug mode is much harder on perf since it will happen a lot, yet is much more likely to be a concern with a typical usage of SIMD stuff such as "draw a million triangles, now" or "encode/decode thousands of digital subsamples of audio, now". So, "We are at least mildly against panicking on debug overflows because the perf concerns are much higher-pressure on testing SIMD code, and also because we think it results in an antipattern" seems like sound reasoning to me. |
If we go with this, we should include a note to this effect in our documentation. |
Cryptography occasionally benefits from checked arithmetic, but offhand I can't think of a cryptographic SIMD use case which needs anything other than Also generally where checked arithmetic is appropriate in cryptographic use cases it's an "always on" sort of thing and not the |
We discussed this on 2021-02-08 and came to a consensus that we should avoid branching in our API, generally, unless it makes sense to always check for a branch. Here it doesn't, really, and, well, it might be UB in certain languages but it certainly isn't that in Rust. And SIMD intrinsics for specific architectures (as far as we are aware) do not define overflow as UB either, since you're just compiling relatively "directly" to a set of assembly instructions, so we don't think it's exactly a familiar expectation for SIMD programmers. Obviously-ish that means that we're still having some equivalent of the We further discussed this on 2021-02-15 and are even currently inclined against providing the |
Could be worth pointing out in * ops docs like |
Remove overflow panic from divrem and add basic docs to Simd<T, N> This finishes normalizing Simd<T, N> to being approximately equivalent to Simd<Wrapping<T>, N> for all implemented operations I can think of. It also documents this fact, allowing this to close #56.
Per topic, this affects our vector implementations of Add, Sub, and Neg.
This came up during discussion for #54 and #55.
The text was updated successfully, but these errors were encountered: