-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Add f16
and f128
float types
#3453
Conversation
Fwiw this table describing platform support should be more or less accurate now (thanks to all the platform experts who helped out). https://hackmd.io/@8W5l8q6-Qyyn_vKh2-L0RQ/rJpZsmcdh. Maybe worth pulling the f128 and f16 columns into this RFC? Would you consider including |
IMHO, |
@tgross35 No, This RFC only mentions other languages as justification for the Rust types and to help implementers align the types with the existing work done on IEEE 754-compliant types in LLVM/C/C++/GCC, not just any type in those languages. |
Fair enough; in the meantime I reserved the crate name |
- Rename doubledouble to f64f64 - Add architecture info about x86 and arm (as suggested) - Add description to target related types (as suggested) - Add link to IEEE-754 and LLVM LangRef
Just got here via This Week in Rust: it's really unclear to me how #3451 and #3453 are related. Is #3453 a newer instance of #3451 that restricts the set of types to be added? If so, should #3451 be closed? I think it would be useful to clarify this relation in the first comment to make it explicit for readers. |
@djc The intention is to proceed with #3453 first, since |
Okay, maybe clarify this in the initial posts for both PRs? |
A few last things I can think of that might be worth considering (including some nits):
Other than that, I think somebody from the lang team will need to say what changes might be necessary before it can be nomincated for discussion. (Maybe @scottmcm? I think you are the resident expert on hardware-level types) |
I think that's out-of-scope for this RFC, even in that section. It should be sufficient to say that more exist.
The RFC text already explicitly describes why. The types f16 and f128 are IEEE 754 while the others are not. The document mentions the text "IEEE 754" ten times. |
"Motivation" currently mentions that this RFC does not cover those types, but no reason is given. I meant to give an explicit note saying that it was considered and decided against (just to provide an easier path for more straightforward types) - i.e., the "Rationale" for why this RFC was split at all. Mentioning 754 is good to give scope, but RFCs also need to explain why their scope was chosen, and document the decision-making process that got there. |
Some other RFCs to maybe crosslink or take from:
|
Re: GPU Graphics GPUs are basically entirely ieee for all of their floats. We do have f16s on the gpu so a project like rust-gpu (which runs rust on the gpu) would be able to use native support for f16 to generate code using f16 on the gpu. Metal seems to be the only one that supports bf16 (in addition to f16) in modern graphics focused GPU apis and this was a very recent addition, I believe with the M2. CUDA supports both bf16 and f16 as well. Having a native f16 type would certainly make uploading/reading f16s more convenient but it's not something that we need on the cpu. |
This comment was marked as resolved.
This comment was marked as resolved.
I think this would be good for bindgen as some people had requested support for |
Honestly, this is one of the big reasons why I advocated for the inclusion of these to be unconditional, since it means just about any crate can implement traits for these types without having to worry about where it's being used, and stuff like Rust-GPU can just make use of that because it's available. If you had to conditionally include these types every time they were used it would be a big hassle and then native users might not be able to use it as often. Binary crates basically don't care about the conditional inclusion since they've already only built for the targets they care about, whereas library crates care a lot about it since they have no idea who's going to be using their crates. I've seen and written code full of spaghetti |
The reason I suggest addressing code size via a separate filter mechanism is that every possibly-absent language feature or |
That's not entirely true, C++ will use lock-based fallbacks for atomics on targets that don't have hardware support. Rust decided not to do that and just doesn't provide the I get that people want to opt-out of softfloats, but given that we already have targets with softfloats for f32/f64, I do feel like making that work is a separate RFC to this one. f16/f128 should then just pick up the same approach. |
those aren't lock-free so I consider them to not be effective. |
I think it could make sense to add The case of a library using To me, the bigger concern is related to binary size. Some growth in I am also curious how C/C++ does |
In C++ these types are optional and can be tested using feature test macros Quote from https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1467r9.html#test-macros:
|
I agree with this comment. The situation with floating point is arguably not ideal, but that doesn't need to stop us from adding additional useful types. @rfcbot reviewed The thing I would most like to see in the RFC is a summary of which targets, particularly Tier 1 if any, would need softfloat implementations. |
@tmandry This RFC already lists hardware targets that have hardware |
Any clue how I know that wanting to forbid softfloat is a concern, but can you clarify the size concern? I am not sure if it is just the size of |
Performance cliffs and documentationTaking a closer look at the RFC, it sounds like most Tier 1 platforms don't support hardware acceleration of these types. That does qualitatively change how I view the RFC. Right now if you're targeting Tier 1 platforms you can grab any of the builtin float types and not think too hard about it, whereas after this RFC you'll have to reason about which ones are hardware accelerated. Does a user's behavior actually change based on this information? The counterargument would be "either you want the added precision or you don't; you should figure that out and, if you care about performance, you should also run benchmarks." That said, not everyone has time to do all the things they "should" do, and knowing where the performance cliffs lie is a very useful shortcut. I think we can solve the performance question with clear documentation on which platforms support acceleration, and would like to see that before stabilizing these types. Currently the docs on primitive number types don't seem to say anything about this. MotivationI also think this raises the bar in terms of motivation. The RFC presents a pretty good motivation, but it would be even better if it contained a list of actual cases where the lack of these types in the standard libraries was a hurdle to users (e.g. #3453 (comment)). The argument that it makes it more convenient to format floats in a binary format (e.g. for GPUs) is a good one, but it raises questions about whether we should support other types like |
It really depends on the target (not only arch, but also OS and ABI): GCC seems to support float128 on more targets ( |
Since I was curious about how exactly this would work, I decided to take a look at how existing floating point maths is emitted on a The result is, it always emits a function call to the relevant embedded ABI function: godbolt link So, you're right that code bloat is a concern, if these are always included in the resulting binary and LTO is never done. Which, I'm not sure. While there's certainly a lot of work to be done on this, it's clear that a lot of people not using these floats in embedded circumstances (or others where binary size is relevant) have already figured out how to get around these restrictions, likely by ensuring that LTO is always performed. So, while there's always room for improvement there, it's worth mentioning that this doesn't really change the problem, and I don't think that constantly avoiding new things that might add extra code is a very sustainable practice, and we should instead focus more heavily on ensuring that in cases like these the unused functions are never added to the resulting binary, either because they're linked in an external library or because they're just part of a special LTO that always gets performed. |
You don't even need LTO. Normal linker operation will only include symbols from static libraries (such as libcompiler_builtins.rlib) that are actually referenced. |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this in FCP, the main content is agreed upon However, there were some things that came up during the design meeting that should be addressed before merge, mostly about motivation.
I added notes from the meeting plus a handful of polish things to help get this ready for merge.
# Motivation | ||
[motivation]: #motivation | ||
|
||
The IEEE 754 standard defines many binary floating point formats. The most common of these types are the binary32 and binary64 formats, available in Rust as `f32` and `f64`. However, other formats are useful in various uncommon scenarios. The binary16 format is useful for situations where storage compactness is important and low precision is acceptable, such as HDR images, mesh quantization, and AI neural networks.[^1] The binary128 format is useful for situations where high precision is needed, such as scientific computing contexts. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The IEEE 754 standard defines many binary floating point formats. The most common of these types are the binary32 and binary64 formats, available in Rust as `f32` and `f64`. However, other formats are useful in various uncommon scenarios. The binary16 format is useful for situations where storage compactness is important and low precision is acceptable, such as HDR images, mesh quantization, and AI neural networks.[^1] The binary128 format is useful for situations where high precision is needed, such as scientific computing contexts. | |
The IEEE 754 standard defines many binary floating point formats. The most common of these types are the binary32 and binary64 formats, available in Rust as `f32` and `f64`. However, other formats are useful in various scenarios. The binary16 format is useful for situations where storage compactness is important and low precision is acceptable, such as HDR images, mesh quantization, and AI neural networks.[^1] The binary128 format is useful for situations where high precision is needed, such as scientific computing contexts. |
I wouldn't call these scenarios uncommon since we are advocating for supporting them 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be dishonest to not say they are uncommon. 99% of use cases don't need 16-bit or 128-bit floats (thus, the reason most languages have been fine without them so far). But also, most use cases don't need 32-bit floats either (thus, the reason many languages like JavaScript and Python have their only float type as 64-bit). Our argument advocating for supporting these formats is that the 1% of use cases greatly benefit from language support and that this deserves to be a core feature in the Rust language, just like 32-bit floats.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe "less common" then? Doesn't really matter since it's passed RFC, uncommon just sounds a bit more like we maybe shouldn't be supporting it
The main unresolved parts of this RFC are the implementation details in the context of the Rust compiler and standard library. The behavior of `f16` and `f128` is well-defined by the IEEE 754 standard, and is not up for debate. Whether these types should be included in the language is the main question of this RFC, which will be resolved when this RFC is accepted. | ||
|
||
Several future questions are intentionally left unresolved, and should be handled by another RFC. This RFC does not have the goal of covering the entire IEEE 754 standard, since it does not include `f256` and the decimal-float types. This RFC also does not have the goal of adding existing platform-specific float types such as x86's 80-bit double-extended-precision. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have come to consensus that this RFC will only support f16 and f128, so all these unresolved questions can be removed.
Unresolved question to add: based on @scottmcm's comment #3453 (comment), I don't know if we will be able to support f128 parsing at first. It requires changes within our float parsing library that we wouldn't want to do if there is any notable impact, so just note this as to be determined
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, it's resolved in that it's not the goal of this RFC to add those features, but it's still unresolved in terms of what will be done in the future.
As for f128 parsing, that seems like an implementation detail that needs to be figured out by the implementers to ensure we support f128 parsing. I don't think it's meaningful for this RFC to say "we don't need f128 parsing", if it's missing for now that's fine, but long-term I don't see a reason to not have it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that since they other float types are covered in Future Possibilities
they don't need to be here. Usually Unresolved Questions
are the things that need to be figured out between the RFC being accepted and the feature being stabilized, Future Possibilities
are out of scope things that could go in other RFCs. (I know the template has out of scope things in both, but I don't see any accepted RFCs that actually put them under unresolved questions)
|
||
Both this RFC and RFC 3451 are built upon the discussion in [issue 2629](https://github.com/rust-lang/rfcs/issues/2629). | ||
|
||
The main consensus of the discussion thus far is that more float types would be useful, especially the IEEE 754 types proposed in this RFC as `f16` and `f128`. Other types can be discussed in a future RFC. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this to "rationale and alternatives", say a bit more about why f80/doubledouble were rejected as part of this RFC (because we want to support the most standard type)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if it's worth restating the details of float types not a part of this RFC. It should be sufficient to say in this section that there are other types, and list a few in "Future possibilities".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a one sentence statement at the end of future possibilities "These types were not included as part of this RFC since their implementation is more open to interpretation, this RFC focuses on well-defined types". Just as a hint to anyone reading this in a few years why we didn't include those types (in the case that the other RFC doesn't go forward).
But, I'm indifferent
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. This will be merged soon. |
Co-authored-by: Trevor Gross <[email protected]>
Thanks for putting the effort on pushing this :) |
This RFC has been merged, and we've opened a tracking issue: rust-lang/rust#116909 Thanks go out to the authors of this RFC for making Rust better by drafting it and pushing it through to acceptance. |
…cs#3453 to be available in stable rust.
Rendered
See the discussion leading up to this RFC in issue #2629, and see the RFC for further floating point types at #3456. This RFC is mostly a subset of what was originally proposed in #3451, and was split off to provide an easier path to consensus for types that don't have as many debatable implementation aspects.
Tracking issue: rust-lang/rust#116909
Editor: Link to FCP proposal: #3453 (comment)