Repository navigation
UnsafeAtomics v0.4.0
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
UnsafeAtomicsLLVMextension is gone, andLLVMPtrsupport is always available. - Floating-point
max!andmin!follow Julia's semantics, so a NaN propagates. Version 0.3 emittedatomicrmw fmax/fminonLLVMPtr. The newfmax!andfmin!keep the IEEE maxNum/minNum behavior. - The default scope is renamed from
nonetosystem.noneremains as an alias, but code that dispatches onLLVMSyncScope{:none}has to switch toLLVMSyncScope{:system}. Scopes no longer print as LLVM IR. The default scope is stillsystemon every pointer type. GPU front-ends that want device-scope atomics should passdevice. - On x86,
fence(seq_cst)is a plainfenceinstruction, as inThreads.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, aseq_cstfence 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_loadand friends), which are now public.
New features
- Public scopes
singlethread,subgroup,workgroup,deviceandsystem, plusUnsafeAtomics.SyncScope(name)for target-specific scopes. Every operation and fence takes one. - Orderings and scopes can be passed as
Symbols. - The
volatile,alignandweakkeywords, and afailure_orderfor compare-and-swap. - New operations:
inc_wrap!,dec_wrap!,sub_cond!,sub_sat!,fmax!andfmin!. - Support for 8-bit integers,
Bool,Float16,BFloat16,Int128and 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.BFloat16that needed a compare-and-swap loop threw aMethodError.