-
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
Suggestions for additional floating-point types #2629
Comments
#[cfg(feature = "real_t_is_double")]
type real_t = f64;
#[cfg(not(feature = "real_t_is_double")]
type real_t = f32; |
A better suggestion would be f16 support, as it is common in graphics. |
Are f16 used much in intermediate calculations? I know it is used commonly as a storage format, but that last time I checked this (I wrote a Pre-RFC on this on internals a while back, but I'm a bit fuzzy on the details), a lot of the calculations involving f16 on most platforms is done by casting to f32, performing the op, the cast back to f16. If that is the case then having native f16 support may not be that important. Adding the ability to use the |
How about
|
@Coder-256 In C++, |
@aaronfranke Could you please clarify what you mean? What I was trying to say is that Rust currently does not have any support for floats larger than 64 bits (8 bytes), for example, There was also a separate issue with |
I wasn't disagreeing with you, I was just adding information. Sorry if I wasn't clear. |
@aaronfranke I absolutely agree, both f128 and f80 would be very useful, especially for FFI (for example, Swift already has |
old things never be gone, I wanna push this. rust is a system language not a script language, need compat old things. |
I wanna push add support for fp80 and fp128... any help need? |
Like rust-lang/rust#38482 does |
Even on modern x86 which has similar or equal speed between most
#[cfg(real_is_f64)]
type real = f64;
#[cfg(not(real_is_f64))]
type real = f32; then you can control via ... Regarding suggestions of f80 What would I'd be in favor of a I'd be in favor of f16, and tentatively f128 since EDIT: I hadn't noticed that sfalker said the exact same thing as my first point >_> |
We have a fact that f80 are broadly used, and in forseable future, that's will continue. We have no need a soft f80 impl, just make on x86 platfrom f80 works is enough. Anyway a soft f80 may be a better option for cross platform consideration. |
several architectures have hardware support for |
For platform have f128, implmenet f80 would not cause significant performance down |
@thomcc These are all ideas, not everything in the OP is relevant anymore since it has been discussed. I think That said, |
may be we can add f16 f80 and f128 in a single shot? |
f16 has uses in neural networks as well. There are actually many problems with using f80, especially if we do not ship a soft float to cover it... it would not be a type defined by an abstraction, frankly, it would be a type defined by Intel's hardware quirks, and we would only be adding more on top of it. One of the nice things about Rust is that it is highly portable right now, so I do not think it makes sense to add such a non-portable type to the language and limit portability that much, though a language extension that makes it simpler to define and use such a non-portable type would make sense. |
I can't say for sure about the other arches, but PowerPC's is not IEEE-754-like at all — it's double-double. It would not help for implementing a sane f128 nor would it help implement a f80.
I don't think this is really true (we can quibble over significant, I guess), but regardless rust doesn't exclusively target architectures in the sets
I mean, it's not mentioned in IEEE-754 2019. It's not hard to imagine what it looks like, admittedly. Anyway, I think once inline asm is stable someone who really wants f80 could implement it as a library on x86/x86_64. This wouldn't solve the issue of FFI (e.g. a |
You're thinking of C's
|
Thanks, you're correct that I was thinking of the PPC long double (__ibm128) type. Unfortunately, I think the existence of 2 separate 128-bit "floating point" types on powerpc only complicates things, although it's nice that at least one of them is moderately sane. |
Full(er) support for IEEE 754 would indeed be very welcome, especially for numerical work.
This is somewhat false, x86's 80-bit floats are extended precision binary64's as specified by IEEE 754. However it's true that these are not very strictly defined, an extended precision binary64 has to have a larger precision than binary64 and the exponent range of binary128. This means that both x86's 80-bit floats and binary128 are examples of valid extended precision binary64's. I'd suggest providing the following types: On x86 platforms, and others that have a native extended precision binary64, a [Edit: further clarified in the relation between 80-bits floats and IEEE 754.] |
So, on the other side of "portable" is "layout". We have a lot of ambiguous-layout types which are not primitive types. However, as far as I am aware all the primitive types have a pretty explicit layout, and many of the std composite data types like Vec etc. have most of their layout dialed in as well. Here we'd have two possible layouts on a numeric type which should be as simple as possible, and |
I'm not too sure what you mean by 'layout' in this case, it's true that extended precision floats do not have to conform to a certain bit format. If you refer to the memory layout of complex data types, I'm not sure if there are any guarantees here anyway as I wouldn't be surprised optimisation passes can and do change these kinds of layouts. I didn't give much thought to the syntax of Most do seem to agree on including all the common IEEE 754 types, which is, I think, the main goal of this issue. Something similar to Fortran's I'd have to check Rust's current support for other parts of IEEE 754 first. There are very few languages with good support for the hardware's capabilities in this area and those that do tend to be rather unsafe. Numerical analysis and other scientific computing do seem to be a great fit for Rust, so I think it's worth looking into this. [Edit: typos and clarification] |
I would expect One interesting side-note: PowerPC v3.0 includes an instruction for converting float types to
|
Turns out that the only supported
This is similar to how |
No need to, In many languages computations with floating point numbers aren't guaranteed to be identical on different targets. On x86_64, for instance, doubles were/are often stored in 80-bit registers, it's only when they are written to memory that they are truncated to 64 bits. In strict mode the JVM thus has to write every floating point value back to memory between operations to guarantee identical results on different architectures. [Edit: formulation was ambiguous.] |
Just asking as a curious observer - has an official RFC for this gotten any movement? The only pre-rfc I can find is this one which has been long closed. Recently stumbled into the pain of varying double/long double support in c and was wondering if rust outdoes it |
I would just like to say that I would love to have f128 support in rust as well. It can be useful, and even necessary, for some scientific computations. |
Opened an issue without realizing f16 was covered here.
My understanding is that _Float16 is a portable arithmetic type, defined in the C11 extension ISO/IEC TS 18661-3:2015), so it would be nice if Rust exposed something similar. |
On the topic of hardware support, I'll add that RISC-V's Q extension provides quadruple-precision floats, so if Rust added Even without hardware acceleration, it would still be useful to have this much precision available via software emulation at the language and standard library level. |
'f16' and 'fp128' would be particularly useful in combination with std:simd, especially for running rust on things like a GPU. |
|
if you need high precision floats but can't wait, you can use https://docs.rs/rug/1.19.2/rug/struct.Float.html |
At this point I think this more or less just needs a RFC, right? (No I am not volunteering to write it) I think that most everyone here would be on board with a minimal implementation like this: /// Available on platforms that support f16
/// ARM and AArch64 have this to my knowledge with __fp16
#[cfg(target_has_f16)]
f16
/// Available on platforms that support true 128-bit floats
#[cfg(target_has_f128)]
f128;
/// Exact semantics of c `long double`
core::ffi::c_longdouble;
/// ...maybe? I don't know enough about it
core::ffi::c_bfloat16; And just not supporting 80-bit fake f128 as a native rust type, only via Not positive about f16 as it hasn't been discussed much here. Apple's M1 is the only mainstream platform I know of that has a half precision unit in CPU |
C |
Not depend on, but be able to interface with. E.g. So providing |
GCC and Clang/LLVM support |
afaict the standardized C keyword is |
I was imagining that |
The wiki page actually has a good summary on this, under the "computer language support" page. I suppose that I guess the use of I think somebody just needs to take a stab at writing an RFC and trim out features that can't reach consensus. I haven't seen anybody arguing things like "rust should not have a f128/f16 type at least on platforms that support real f128/f16", so it's just a matter of structuring the details into something better than a long github issue discussion :) You've been super active on this issue for 4 years @aaronfranke - do you maybe want to write it up? Should be a pretty easy RFC. Just fill out this template https://github.com/rust-lang/rfcs/blob/master/0000-template.md and create a PR to that repo (no pressure of course) |
|
Some questions/notes regarding float128 (also applied to float16): Which 'long' float type should be supported?According to LLVM, there're three float types longer than
Although many targets still does not support Which targets should support
|
This all sounds totally reasonable 👍
I don't think that any sort of decisions like this are typically blocked on
Go for it! It sounds like you certainly have the knowledge to write it. It's a team effort anyway, you can create a draft PR as soon as you have some of it typed up, and everyone can help finish/polish it (link it here whenever you do) |
RISC-V has native hardware support for IEEE quadruple-precision 128-bit floats via the Q extension. Most other CPU architectures will need to use software emulation; I would look into how C/C++
There is no configuration, the rule should be that we forget about
That would be great! (also small note, my text above isn't disagreeing with you, just clarifying) |
Note that compiler-rt isn't always available, so we'd still have to port implementations of these for compiler-builtins. It would be good to avoid more situations where this is assumed, which causes significant pain. |
|
Hi there, here is my initial draft for the planned RFC: https://github.com/ecnelises/rust-rfcs/blob/additional-floats/text/0000-additional-float-types.md I know the author has chance to revise it before the decision period, but I’d like to gather some basic comments before it goes into a real RFC, since this is my first attempt to write a Rust RFC. Thanks! |
@ecnelises are you able to open a PR to the RFC repo? It's easier to provide feedback that way. Quick review:
impl From<f16> for f128 { /* ... */ }
impl From<f32> for f128 { /* ... */ }
impl From<f64> for f128 { /* ... */ }
impl From<i8> for f128 { /* ... */ }
// ... But again, easier to shape these things once you open a PR. Thanks for putting it together! |
@ecnelises Looks nice to me overall, I did spot one grammar mistake:
Also I agree with @tgross35 on mentioning architectures, for example we can mention RISC-V which has support for 128-bit quadruple-precision floats via the Q extension (without the Q extension, emulation would be required). For the discussion of what to put in this RFC or what to leave out (@tgross35 mentioned maybe leaving out f80 but including For the drawbacks section, note that not all architectures support |
@ecnelises would you mind opening a PR to this repo with your draft? You can create it as a draft PR to indicate that it isn't ready for final review. Even if you haven't had the time to work on it (completely understandable), I think it would be good for everyone to start thinking about it, and to provide reviews with suggested changes. |
Sorry for the delay! I've created #3451 . Although I still have some changes not finished, I'd be glad to see more comments and revise it. |
I noticed that, like other languages, the only floating-point types built-in are
f32
andf64
. However, only having these can be limiting. I propose addingf128
, and as mentioned in this threadf16
would likely be very useful for some workloads.f128
would not be needed in most programs, but there are use cases for them, and it'd be nice to have it as a language built-in type. RISC-V is able to hardware accelerate them using the Q extension.f16
is a more efficient type for workloads where you need tons of floats at low precision, like machine learning. Hardware using this is already widespread in Apple's neural engine and in mobile graphics.Also, if covering IEEE-754 is desired, then there's also
f256
.Original text:
I noticed that, like other languages, the only floating-point types built-in are
f32
andf64
. However, I often have limitations with just these. I propose the following:, andfsize
,freal
f128
fsize
would be likeisize
but for floats. Basically, use the version that's most efficient for your processor. On modern 64-bit processors with wide FPUs and/or 256-bit SIMD this would becomef64
.Sometimes I want to be able to have a variable for real numbers, or I don't know what precision I want yet. In C++ I can do the following to have an abstract precision that I control via compiler flags:#ifdef REAL_T_IS_DOUBLE
typedef double real_t;
#else
typedef float real_t;
#endif
I propose something similar in Rust, where you can just writefreal
or something and be able to change the precision later with compiler flags. The default would probably bef32
.Finally, it would be nice to have 128-bit floats (
f128
) in the language. These are not normally needed, but there are use cases for them, and it'd be nice to have it as a language built-in type. Some newer processors have 512-bit SIMD chipsets that can process these efficiently, though most don't.If you only implement some of these proposals, that's fine too. Originally posted at rust-lang/rust#57928
The text was updated successfully, but these errors were encountered: