Skip to content

v0.4.0

Latest

Choose a tag to compare

@github-actions github-actions released this 05 Oct 17:30
9920104

UnsafeAtomics v0.4.0

Diff since v0.3.4

UnsafeAtomics 0.4 is the front-end for atomics on CPUs and GPUs. Each operation emits one LLVM atomic instruction with the requested ordering and syncscope. Ptr and LLVMPtr now share a single implementation, and GPUCompiler (2.12 and later) legalizes that instruction for each GPU back-end.

Breaking changes

  • UnsafeAtomics now depends on LLVM.jl. The UnsafeAtomicsLLVM extension is gone, and LLVMPtr support is always available.
  • Floating-point max! and min! follow Julia's semantics, so a NaN propagates. Version 0.3 emitted atomicrmw fmax/fmin on LLVMPtr. The new fmax! and fmin! keep the IEEE maxNum/minNum behavior.
  • The default scope is renamed from none to system. none remains as an alias, but code that dispatches on LLVMSyncScope{:none} has to switch to LLVMSyncScope{:system}. Scopes no longer print as LLVM IR. The default scope is still system on every pointer type. GPU front-ends that want device-scope atomics should pass device.
  • On x86, fence(seq_cst) is a plain fence instruction, as in Threads.atomic_fence(). 0.3 used inline assembly before LLVM 20.
  • Code compiled by Julia for the host CPU uses the system scope for every scope except singlethread. The CPU back-ends don't support other scopes: on x86, for example, a seq_cst fence in any other scope compiled to no instruction.
  • Orderings, scopes and keyword arguments have to be compile-time constants. Anything else results in a dynamic call. Back-ends that pass them through their own functions can call the Val-based primitives (UnsafeAtomics.Internal.llvm_load and friends), which are now public.

New features

  • Public scopes singlethread, subgroup, workgroup, device and system, plus UnsafeAtomics.SyncScope(name) for target-specific scopes. Every operation and fence takes one.
  • Orderings and scopes can be passed as Symbols.
  • The volatile, align and weak keywords, and a failure_order for compare-and-swap.
  • New operations: inc_wrap!, dec_wrap!, sub_cond!, sub_sat!, fmax! and fmin!.
  • Support for 8-bit integers, Bool, Float16, BFloat16, Int128 and pointers. Operations without a native instruction fall back to a compare-and-swap loop, so every operation works for every supported type.
  • With GPUCompiler 2.12, device code gets every instruction the IR can express, with the requested scope. GPUCompiler then renames the scopes for each target.

Fixes

  • Operations on Core.BFloat16 that needed a compare-and-swap loop threw a MethodError.