swift-atomics
swift-atomics copied to clipboard
Implement atomic floats
Implement AtomicValue conformances for Float, Double and Float16. Requirements/constraints:
compareExchangemust compare the underlying encoded bit patterns rather than performing actual floating point comparisons. (I.e., it must consider negative zero different from positive zero, it must consider a NaN value equal to itself, etc.)- We should provide as many direct operations as llvm/clang exposes. It would be nice to at least provide an atomic addition.
- We probably don't need/want an
AtomicFloatingPointprotocol.
I have implemented atomic floating-point implementations in Metal Shading Language, because I needed to accumulate sparse volumetric sums of color data for scene color reconstruction. I used a quick (load)-(floating point add)-(compare-exchange) loop.
Since it might sometimes fail due to conflicting writes, I would attempt to increment other areas of memory while waiting for the first one to be freed. This helped especially with SIMD execution amplifying the performance cost of a collision by a factor of 32. Every floating point operation was called something like “attemptAtomicallyAdd”.
For this package, a blocking alternative would internally call the non-blocking one until it succeeded. However, this means the blocking one would be less transparent to the user, which would impact some bottlenecks in high-performance computing.
We should discuss the following floating point operations for atomics:
- bitwise compare/exchange
- blocking (and failable non-blocking) floating-point compare/exchange
- blocking (and failable non-blocking) versions of cheap elementary operations
The elementary operations I implemented in Metal were:
- add/subtract (two clock cycles)
- multiply and fused multiply-add (three clock cycles)
- negate and absolute value are zero cycles in Metal when fused with other ops, so no implementation was given to them
Designing around my Metal use case doesn’t seem like the most appropriate way to design a library. I recommend offering both bitwise (native instructions) and blocking floating point (where it fetches and loops) comparisons at a minimum. Neither operation will ambiguously be called “compareAndExchange”.
Someone could also unsafeBitCast an atomic reference to one to an integer if they want to unlock the functionality of bitwise comparison.
Furthermore, floating point operations aren’t implemented in the C++ standard library, so we should be very careful to stick with standard naming guidelines. However, I don’t see this addition to Swift-Atomics as being in violation of any standards or of the style of Swift.