Skip to content
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

Additional float types #3451

Closed
wants to merge 3 commits into from
Closed

Conversation

ecnelises
Copy link
Contributor

@ecnelises ecnelises commented Jun 28, 2023

@lygstate

This comment was marked as resolved.

@ehuss ehuss added the T-lang Relevant to the language team, which will review and decide on the RFC. label Jun 28, 2023
text/3451-additional-float-types.md Outdated Show resolved Hide resolved
Comment on lines +103 to +106
# Drawbacks
[drawbacks]: #drawbacks

Unlike f32 and f64, although there are platform independent implementation of supplementary intrinsics on these types, not every target support the two types natively, with regards to the ABI. Adding them will be a challenge for handling different cases.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not every platform supports f32 and f64 natively either. For example, RISC-V without the F or D extensions (ex: ISA string of rv64i). This should be mentioned.

Whatever emulation Rust already does to support f32 and f64 on systems without native support should similarly happen to emulate f128 on systems without native quadruple-precision support.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For riscv without hardware float support there is a defined soft-float ABI. There is not for f16/bf16. Same for x86_64. Many other architectures likely don't have a defined soft-float abi for f128 either. And as I understand it AArch64 doesn't have a soft-float abi at all as Neon support is mandatory and floats are even allowed inside the kernel unlike eg x86_64 where floats are disabled in the kernel to avoid having to save them on syscalls.

text/3451-additional-float-types.md Show resolved Hide resolved
@clarfonthey
Copy link
Contributor

clarfonthey commented Jun 28, 2023

I'm okay with this for the most part, except that I disagree that f16 and f128 should only be limited to targets that support them natively. I think that having target features for float support is a good idea, especially considering how it would help the current situation with floating-point operations in libcore, but I don't think that actually using these types should be gated behind hardware support.

A good example of this is u128, which is not natively supported on many platforms, but still available regardless of target. We can still emulate it, and we can still use it, therefore we can define methods for it. IMHO, gating these types behind target features just adds unnecessary boilerplate for libraries wanting to implement methods for them, and people who are writing performance-sensitive code will already take into account whether these types are fast on the relevant targets before using them.

Additionally, while I don't feel too strongly about it, I don't like the idea of naming the x86 "long double" type f80, since it implies that it's also part of the IEEE 754 standard when it's not. I'm not too against it, though, since it is specific to std::arch.

@lygstate
Copy link

lygstate commented Jun 28, 2023

I'm okay with this for the most part, except that I disagree that f16 and f128 should only be limited to targets that support them natively. I think that having target features for float support is a good idea, especially considering how it would help the current situation with floating-point operations in libcore, but I don't think that actually using these types should be gated behind hardware support.

A good example of this is u128, which is not natively supported on many platforms, but still available regardless of target. We can still emulate it, and we can still use it, therefore we can define methods for it. IMHO, gating these types behind target features just adds unnecessary boilerplate for libraries wanting to implement methods for them, and people who are writing performance-sensitive code will already take into account whether these types are fast on the relevant targets before using them.

Additionally, while I don't feel too strongly about it, I don't like the idea of naming the x86 "long double" type f80, since it implies that it's also part of the IEEE 754 standard when it's not. I'm not too against it, though, since it is specific to std::arch.

f80 is a lot shorter, easy for literal, we can clarify that only f16 f32 f64 f128 are IEEE 754 standard.

Copy link
Contributor

@tgross35 tgross35 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added some more detail in various places, and added core::ffi::c_longdouble (which I'm fairly certain we would want)

text/3451-additional-float-types.md Outdated Show resolved Hide resolved
# Summary
[summary]: #summary

This RFC proposes new floating point types `f16` and `f128` into core language and standard library. Also this RFC introduces `f80`, `doubledouble`, `bf16` into `core::arch` for inter-op with existing native code.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This RFC proposes new floating point types `f16` and `f128` into core language and standard library. Also this RFC introduces `f80`, `doubledouble`, `bf16` into `core::arch` for inter-op with existing native code.
This RFC proposes new floating point types `f16` and `f128` into core language and standard
library. Also, this RFC introduces `f80`, `doubledouble`, and `bf16` into `core::arch` for
target-specific support, and `core::ffi::c_longdouble` for FFI interop.

Copy link

@lygstate lygstate Jun 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest use these symbols, all start with f prefix that consistence

  • f128: C _Float128, LLVM fp128, GCC __float128
  • f16: C _Float16, LLVM half, GCC __fp16
  • f16b: C++ std::bfloat16_t, LLVM bfloat, GCC __bf16
  • f80e: LLVM x86_fp80, GCC __float80
  • f64f64: LLVM ppc_fp128, GCC __ibm128

And these symbols can be used as literal suffix as is

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for f16b in favor over bf16 for consistency, I liked that about @joshtriplett's original proposal.

I don't think we should introduce something like f128x - doubledouble or something like the GCC or LLVM types would be better IMO. Reason being, it's kind of ambiguous and specific to one architecture - PowerPC is even moving away from it. Better to give it an unambigous name since it will be used relatively rarely.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we should use bf16 rather than f16b since that is widely recognized whereas f16b isn't, and f64_f64 instead of f128x since it really is 2 f64 values and could be easily emulated on any other architecture (do not use f64x2 since that's already used by Simd<f64, 2>). also f<N>x names are more or less defined by IEEE 754 to be wider than N bits, so e.g. f64x would be approximately any type wider than f64 but less than f128 such as f80, f16x could be the f24 type used by some GPUs for depth buffers. so logically f80x would need to be more than 80 bits and f128x would need to be more than 128 bits.

Copy link

@lygstate lygstate Jun 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for f16b in favor over bf16 for consistency, I liked that about @joshtriplett's original proposal.

I don't think we should introduce something like f128x - doubledouble or something like the GCC or LLVM types would be better IMO. Reason being, it's kind of ambiguous and specific to one architecture - PowerPC is even moving away from it. Better to give it an unambigous name since it will be used relatively rarely.

f64f64 is OK, no need the underscore looks like doubledouble, f80e instead f80x if f80x is not acceptable

Still vote for f16b, It's rust specific, we can create relationship between bf16 and f16b in rust, that's won't be a burden.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about f64x2 to indicate it's two f64 glued together?

Copy link

@lygstate lygstate Jun 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do not use f64x2 since that's already used by Simd<f64, 2>


All operators, constants and math functions defined for `f32` and `f64` in core, are also defined for `f16` and `f128`, and guarded by respective conditional guards.

`f80` type is defined in `core::arch::{x86, x86_64}`. `doubledouble` type is defined in `core::arch::{powerpc, powerpc64}`. `bf16` type is defined in `core::arch::{arm, aarch64, x86, x86_64}`. They do not have literal representation.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
`f80` type is defined in `core::arch::{x86, x86_64}`. `doubledouble` type is defined in `core::arch::{powerpc, powerpc64}`. `bf16` type is defined in `core::arch::{arm, aarch64, x86, x86_64}`. They do not have literal representation.
The `f80` type is defined in `core::arch::{x86, x86_64}` as 80-bit extended precision. The `doubledouble`
type is defined in `core::arch::{powerpc, powerpc64}` and represent's PowerPC's non-IEEE double-double
format (two `f64`s used to aproximate `f128`). `bf16` type is defined in `core::arch::{arm, aarch64, x86, x86_64}` and represents the "brain" float, a truncated `f32` with SIMD support on some hardware. These
types do not have literal representation.
When working with FFI, the `core::ffi::c_longdouble` type can be used to match whatever type
`long double` represents in C.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I did not add the mention of longdouble yet. More things need to be clarified:

  • Is there always only 1 long double for each (arch, abi, os) tuple? For example, powerpc64le-unknown-linux-gnu can use either double or doubledouble or IEEE binary128 as long double by -mabi=(ieee|ibm)longdouble and -mlong-double-(64|128).
  • Is mangling of long double the same regardless of its underlying semantics?
  • Some targets (also powerpc64le for example) support .gnu_attribute, so that linker can differentiate objects compiled by different long double ABI. Should Rust programs using c_longdouble emit such attribute?

text/3451-additional-float-types.md Outdated Show resolved Hide resolved
text/3451-additional-float-types.md Outdated Show resolved Hide resolved
text/3451-additional-float-types.md Show resolved Hide resolved
text/3451-additional-float-types.md Outdated Show resolved Hide resolved
text/3451-additional-float-types.md Outdated Show resolved Hide resolved

`f128` is available for on targets having (1) hardware instructions or software emulation for 128-bit float type; (2) backend support for `f128` type on the target; (3) essential target features enabled (if any).

The list of targets supporting `f128` type may change over time. Initially, it includes `powerpc64le-*`.
Copy link
Contributor

@tgross35 tgross35 Jun 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The list of targets supporting `f128` type may change over time. Initially, it includes `powerpc64le-*`.
The list of targets supporting `f128` type may change over time. Initially, it includes `powerpc64le-*`.
`x86_64-*` and `aarch64-*`

I don't know for sure what targets support it, but we should aim to at least support the major 64-bit CPUs
here at first

There is also a risc target per @aaronfranke here #2629 (comment) but I'm not sure how rv64gQc maps to our riscv64gc

@tgross35
Copy link
Contributor

tgross35 commented Jun 28, 2023

I agree with the comments about f80; I think I would rather see it named x86_fp80 (to match the LLVM intrinsic) to make it clear that it is not a standard type and to discourage use.

A good comment from the issue thread that summed this up: #2629 (comment)


All operators, constants and math functions defined for `f32` and `f64` in core, are also defined for `f16` and `f128`, and guarded by respective conditional guards.

`f80` type is defined in `core::arch::{x86, x86_64}`. `doubledouble` type is defined in `core::arch::{powerpc, powerpc64}`. `bf16` type is defined in `core::arch::{arm, aarch64, x86, x86_64}`. They do not have literal representation.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bf16 is supported on a wide range of newer architectures, such as powerpc, x86, arm, and (WIP) risc-v. imho it should not be classified as architecture-specific but instead more like f16

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeap bf16 should be simulated when target arch is not supported

@thomcc
Copy link
Member

thomcc commented Jun 28, 2023

Note that supporting 80-bit floats (at all) might complicate the situation being discussed in rust-lang/rust#113053, which suggests that we might be able to manipulate the control word (to set a 53 bit mantissa) in order to get more consistent behavior for f64.

@the8472
Copy link
Member

the8472 commented Jun 28, 2023

Would it make sense to consider a subset? Especially the 16bit floats are a growing field compared to the legacy types.

@tgross35
Copy link
Contributor

I started trying to get together a better collection of what platforms & features support the different types to serve as a reference when implementing and help steer choices for this RFC (we can pull the contents in at some point). The doc is editable (if logged in), please add info & links if you know of any: https://hackmd.io/@8W5l8q6-Qyyn_vKh2-L0RQ/rJpZsmcdh/edit

Also, zulip thread for this RFC: https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/f16.20.26.20f128.20RFC

@programmerjake
Copy link
Member

programmerjake commented Jun 29, 2023

note that PowerISA's BFP128 extension has a specific instruction to aid emulation of f80: xsrqpxp

@kpreid
Copy link

kpreid commented Jun 29, 2023

I'm okay with this for the most part, except that I disagree that f16 and f128 should only be limited to targets that support them natively.

+1 — GPU programming may involve storing and copying f16s without necessarily performing any arithmetic on them except possibly a final conversion to/from f32. Therefore it will be useful to be able to have the guaranteed type even if it has no supported arithmetic operations, simply for interoperability between crates that interact with [f16] slices copied or mapped from the GPU.

@Muon
Copy link

Muon commented Jun 29, 2023

Note that supporting 80-bit floats (at all) might complicate the situation being discussed in rust-lang/rust#113053, which suggests that we might be able to manipulate the control word (to set a 53 bit mantissa) in order to get more consistent behavior for f64.

I would not say that it complicates anything. It's just another setting of the control word. In any case, such concerns are to be addressed in LLVM, not rustc. If my suggested changes are implemented and accepted, rustc doesn't need to change anything.

Also I wholeheartedly support the 80 bit support. It makes life a lot nicer working with the x87. Though I agree that the name should make clear that it's not an IEEE format.

I also agree that f16 and f128 should be emulated if necessary. Consistent universal support is invaluable.

@aaronfranke
Copy link
Contributor

@the8472 If it helped with acceptance, I think splitting f16 and f128 to get those merged in faster would be very welcome. There is less to be debated with those, their behavior is highly standardized by IEEE, they are desired on all platforms, and their names are obvious, so the main challenge is implementation. The others have complexity that needs debate including interop with other languages and if they should be available on all platforms.

@joshtriplett
Copy link
Member

Also I wholeheartedly support the 80 bit support. It makes life a lot nicer working with the x87. Though I agree that the name should make clear that it's not an IEEE format.

Agreed, though I definitely think it should stay in arch as a target-specific type.

By contrast, I think f16b (or whatever we end up calling it) should be available on all targets, like f16 and f128.

@workingjubilee
Copy link
Contributor

I agree that we should basically consider f128 and f16 separately from the rest, especially as "long double" has a bunch of thorny "gotchas" around its repr, e.g. on systems with the x87 FPU it is not guaranteed that C's "long double" is indeed the fully extended 80-bit float.


All operators, constants and math functions defined for `f32` and `f64` in core, are also defined for `f16` and `f128`, and guarded by respective conditional guards.

`f80` type is defined in `core::arch::{x86, x86_64}`. `doubledouble` type is defined in `core::arch::{powerpc, powerpc64}`. `bf16` type is defined in `core::arch::{arm, aarch64, x86, x86_64}`. They do not have literal representation.
Copy link
Member

@RalfJung RalfJung Jun 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For people that have never heard of bf16 or doubledouble (which I assume are 16 and 128 bits in size, respectively), it would be good to link to some sort of document explaining them, and how they differ from f16 and f128, respectively.

Also the RFC needs to say what their semantics are, if IEEE doesn't specify them.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nobody seems to agree on bf16 semantics:
arm has both round as normal with subnormals supported and round to odd with subnormals not supported.
x86 has round to nearest with subnormals not supported.
powerpc has round as normal with subnormals supported.
all isas have round towards zero with subnormals supported (just f32::to_bits(v) >> 16).

@clarfonthey
Copy link
Contributor

clarfonthey commented Jun 30, 2023

Since a lot of people are sort of dancing around it, here's my take on a precise proposal for how to modify the RFC:

  1. f16 and f128 should be unconditionally added to the language with the same semantics as existing f32 and f64.
  2. There should be a minimal alias for c_longdouble in the core::ffi module, but its semantics should be explicitly dialed back for the time being.

For f16 and f128 semantics, it should support the generic {float} literals as well as explicit suffixes. They should support basic arithmetic operations via core, and advanced arithmetic operations via std. This can be tweaked as the semantics for f32 and f64 are further refined.

For c_longdouble, we should ensure that From conversions always exist from f16, f32, and f64, which will always happen for f128 but might additionally be required for things like the non-standard 80-bit floats. However, beyond that and ABI compatibility, I don't think anything else should be offered initially. We can eventually export all possible versions of this in core::arch, but for now, the only cases where it should work perfectly should be when it corresponds to f64 or f128; all other cases should be effectively an opaque type as far as most users are concerned.

It should be relatively easy to add in other non-standard float types as experimental in the meantime. My proposal is that these should work very similarly to how I present c_longdouble here: they should have some sense of ABI compatibility with C, and From conversions should be added whenever possible, but no arithmetic until we nail down the semantics. People can implement their own versions with inline assembly and other unsafe code in the meantime, but at least crates can all agree on what the types are.

My suspicion for something like bf16 is that it would be already quite useful if people just had methods to truncate f32 values into it, since this is very fast and it's what bf16 was designed for. This would require some sense of how we want to do "truncating conversion" in general (right now as is the only reasonable method, but we want to generalise that to a trait), but deciding on how those conversions work isn't necessary to simply add the type in an unstable way.


EDIT: Since it's worth adding this after the fact, I wanted to explain a little bit more on why I think these dialed-back semantics are important. Right now, the biggest issue with floating-point semantics is how values are affected by arithmetic operations, like whether NaN payloads are preserved or how rounding is done. However, the one thing we do know about these formats is how you interpret a single value in memory, and that's why we can easily convert to and from these formats to IEEE 754, either exactly or by truncating. This should let us still create a standard type that is ABI-compatible with C (± any nonstandard extensions for particularly weird formats) without actually taking a firm stance on the semantics quite yet.

The other big question about semantics is how the exact values in memory are preserved between operations, particularly the NaN payloads, although that has largely been decided with the stabilisation of total_cmp and from_bits/to_bits on the existing float types. So, it wouldn't be that out of the question to simply support storing these types to their exact specs, quirky payloads and all, while letting end users decide how the actual arithmetic operations behave.

@Larsouille25
Copy link

is there a real demand for f16 ? Because, yes there just 2 bytes long but f16 are not very precise

@aaronfranke
Copy link
Contributor

@Larsouille25 f16 is useful when you want to store a lot of float data with minimal size, and don't need much precision. For example, floating-point HDR images can be stored in f16, the 10-bit mantissa being more precision bits than the standard 8-bit 0-255 range, and the 5-bit exponent being more than enough. See EXR and formats RGBAh, RGh, Rh.

Another example, quantized mesh data, for some use cases of meshes you really don't care if a vertex is a fraction of a millimeter off, and meshes have a lot of vertices, so using f16 can half the required memory size.

@clarfonthey
Copy link
Contributor

Also adding onto what @aaronfranke said, in general, values between 0 and 1 are quite precise for f16s, since they have a 10-bit significand. These values not only are useful for colour, but loads of different things only need to store a float in this range and using up half the memory is quite a benefit.

@aaronfranke
Copy link
Contributor

I opened #3453 which is mostly a subset of this RFC, a lot of text was copied from here. It only includes f16 and f128, and changes them to be available on all targets instead of conditionally available.

@Nemo157
Copy link
Member

Nemo157 commented Jul 2, 2023

Prior art should also mention https://crates.io/crates/half, which is at ~2million downloads/month, showing there is a lot of demand for f16 (I'm not sure if there's a similar crate for f128).

@aaronfranke
Copy link
Contributor

@Nemo157 There is already a link to https://github.com/starkat99/half-rs but a crate link may be better.

@Nemo157
Copy link
Member

Nemo157 commented Jul 2, 2023

Ah, under alternatives. I only checked the prior art section (and I think highlighting the wide usage in the RFC would be useful).

@tgross35
Copy link
Contributor

tgross35 commented Jul 2, 2023

I opened #3453 which is mostly a subset of this RFC, a lot of text was copied from here. It only includes f16 and f128, and changes them to be available on all targets instead of conditionally available.

With this in mind, it would probably be good to shave f16 and f128 out of this RFC and make this only about the compatibility types in core::arch / core::ffi. And bf16, wherever that may end up (side note: the link to Josh's bf16 proposal in this RFC should go to the PR #2690 and not to the file on the branch).

@lygstate
Copy link

lygstate commented Jul 3, 2023

@tgross35 Your link is broken, I updated a new one https://hackmd.io/8Ptau058RmGqV0ZYJ49S9A

@tgross35
Copy link
Contributor

tgross35 commented Jul 3, 2023

Thank you, formatting fixed: https://hackmd.io/@8W5l8q6-Qyyn_vKh2-L0RQ/rJpZsmcdh

@ecnelises
Copy link
Contributor Author

I opened #3453 which is mostly a subset of this RFC, a lot of text was copied from here. It only includes f16 and f128, and changes them to be available on all targets instead of conditionally available.

I'm still doubting if it's feasible to support it on all platforms. From the view of backend (LLVM, more especially), half and fp128 are not always 'implemented' or even 'defined'.

(let F be either f16 and f128)

  1. If target supports instructions for F, everything is okay.
  2. If target ABI supports software emulation for F, everything is okay.
  3. If target ABI does NOT support software emulation for F, but there's another type with same storage (size/alignment), could it be used as storage type of F (and sure, F is storage-only in such case)? This may cause ABI compatibility issue.
  4. If target ABI does NOT support emulation for F, and no such type exists as storage-only equivalent. We can do nothing here.
  5. If target ABI supports F, but backend (LLVM, etc.) does not implemented the feature, should compiler also have some guard about it?

@lygstate
Copy link

lygstate commented Jul 3, 2023

I opened #3453 which is mostly a subset of this RFC, a lot of text was copied from here. It only includes f16 and f128, and changes them to be available on all targets instead of conditionally available.

I'm still doubting if it's feasible to support it on all platforms. From the view of backend (LLVM, more especially), half and fp128 are not always 'implemented' or even 'defined'.

(let F be either f16 and f128)

  1. If target supports instructions for F, everything is okay.
  2. If target ABI supports software emulation for F, everything is okay.
  3. If target ABI does NOT support software emulation for F, but there's another type with same storage (size/alignment), could it be used as storage type of F (and sure, F is storage-only in such case)? This may cause ABI compatibility issue.
  4. If target ABI does NOT support emulation for F, and no such type exists as storage-only equivalent. We can do nothing here.
  5. If target ABI supports F, but backend (LLVM, etc.) does not implemented the feature, should compiler also have some guard about it?

don't worry, C++ already have both f16 and f128, that is std::float16_t, std::float32_t, std::float64_t, std::float128_t, std::bfloat16_t

@aaronfranke
Copy link
Contributor

@ecnelises This is a good question, but I disagree about this point:

  1. If target ABI does NOT support emulation for F, and no such type exists as storage-only equivalent. We can do nothing here.

Yes, we can do something here. There is no reason we can't support our own emulation. Any calculation can be performed on a turing-complete computer. The specific details may be a challenge to implementers in some cases, but it is not impossible to support these types everywhere, therefore they should be supported everywhere.

- 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
@ecnelises
Copy link
Contributor Author

@ecnelises This is a good question, but I disagree about this point:

  1. If target ABI does NOT support emulation for F, and no such type exists as storage-only equivalent. We can do nothing here.

Yes, we can do something here. There is no reason we can't support our own emulation. Any calculation can be performed on a turing-complete computer. The specific details may be a challenge to implementers in some cases, but it is not impossible to support these types everywhere, therefore they should be supported everywhere.

If we do plan to implement the types everywhere, the 4 becomes 5. Even no has_f128 guards need to exist, compiler should still provide useful diagnostics if the types are used but not implemented by backend yet.

don't worry, C++ already have both f16 and f128, that is std::float16_t, std::float32_t, std::float64_t, std::float128_t, std::bfloat16_t

I think they're optional? https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1467r4.html

@scottmcm
Copy link
Member

scottmcm commented Jul 6, 2023

Overall, I like the idea of separating out the real IEEE types from the random stuff, and making f16 and f128 not arch-specific.

f80 is a lot shorter, easy for literal, we can clarify that only f16 f32 f64 f128 are IEEE 754 standard.

I don't think that's important for a niche type, though. It doesn't need a name any nicer than __m512i and friends get.

For that matter, what's the goal of having a type for x87's weird things? It's mentioned in neither the Motivation nor the Rationale sections. How much new Rust code is going to be written targeting those types specifically instead of normal doubles? What's the size and alignment of such a type in memory? Are modern chips putting any effort into making it work efficiently, when x87 (and MMX) tend to be avoided by modern compilers?

bf16 [...] These types do not have literal representation.

Why not? It seems odd to me that f16 would support literals but bf16 wouldn't.

Unless "these types" is supposed to be after a newline so it refers to all the arch-specific ones, maybe?

@Jules-Bertholet
Copy link

For that matter, what's the goal of having a type for x87's weird things?

One possibility I could see, is that if Rust some day decides to accept the performance hit and make f64 fully IEEE-compliant on no-SSE x86-32, f80 would allow code that doesn't need full compliance to recover some performance on these platforms.

@tgross35
Copy link
Contributor

tgross35 commented Jul 7, 2023

@ecnelises would you be able to update this RFC to be about bf16, ppc_fp128 and x86_fp80, and reference #3453 as a subset that should be developed first? Specifically, update the PR title to specifically mention those types, and add a link to the other RFC.

We can work on both RFCs in parallel but readers need to be clear about what the relationship between the two is - it's currently ambiguous.

ecnelises added a commit to ecnelises/rust-rfcs that referenced this pull request Jul 10, 2023
This revision also contains comments addressed from reviewers in RFC rust-lang#3451.
@ecnelises
Copy link
Contributor Author

@ecnelises would you be able to update this RFC to be about bf16, ppc_fp128 and x86_fp80, and reference #3453 as a subset that should be developed first? Specifically, update the PR title to specifically mention those types, and add a link to the other RFC.

We can work on both RFCs in parallel but readers need to be clear about what the relationship between the two is - it's currently ambiguous.

Thanks for your and other's comments. I generally agree that a proposal for IEEE-754 compliant f16/f128 and for target specific types are quite different. So I created another one #3456, focusing on bf16, f64f64, f80 and c_longdouble types.

I'm not familiar with Rust community's RFC policy. So I'm in doubt whether kicking off new post directly from another people without previous commit/author information shows enough respect to the original author.

@tgross35
Copy link
Contributor

Thanks for your and other's comments. I generally agree that a proposal for IEEE-754 compliant f16/f128 and for target specific types are quite different. So I created another one #3456, focusing on bf16, f64f64, f80 and c_longdouble types.

I'm not familiar with Rust community's RFC policy. So I'm in doubt whether kicking off new post directly from another people without previous commit/author information shows enough respect to the original author.

There is no policy on this, but consulting before splitting off your PR would have been, well, nice. It would probably be good for the two RFC authors to come to consensus on Zulip about what the relationship among these RFCs should be, and how to harmonize them a bit (or even figure out coauthoring) to help give the community a better picture of what exactly is being proposed. There is an existing floats rfc topic that can be used for discussion https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/f16.20.26.20f128.20RFC

@ecnelises
Copy link
Contributor Author

I think we can close this since #3456 and #3453 were splitted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet