vllm.models.minimax_m3.amd.specialized_decode.mono.sync
¶
Bounded tagged hand-offs and the sticky error word.
The contract, in the LLVM "AMDGPU Memory Model" (llvm/docs/AMDGPUMemoryModel.md, AMM) and AMDGPUUsage "Execution Barriers":
- A pair is one naturally aligned 64-bit atomic, (value | tag << 32),
monotonicat its space's scope (agentfor this GPU's scratch, system for the peer heap). An atomic access is never split, so a load that sees a pair's tag sees that store's value. A triple pair (put_triple, the attention seam) is the same atomic with three bf16 in bits 0 .. 47 under a 16-bit tag, unique between epoch resets (the kernel's EPOCH_LIMIT). - Data a pair announces is stored store-available and loaded load-visible
at agent scope (AMM: agent atomics of 16 to 64 bits,
llvm.amdgcn.av.load. b128;store_dev/load_dev). - Happens-before from producer to consumer: the producer's release fence
before the pair (
publish), the consumer's acquire fence after the poll that saw it (acquire), and within a CTA release,s_barrier, acquire (gpu.barrier; "Execution Barriers": they synchronize). These fences are tagged!{"amdgcn-av", "none"}: they synchronize and keep the compiler from moving accesses across them, but make nothing available or visible. - AMM visibility: a store-available write that happens-before a load-visible read of the same agent is visible to it, so the read returns that write (the previous launch's writes to the location are ordered before it by the kernel boundary).
The av operations are lowered with the agent-scope cache bits (sc1) and
the av-none fences to waits only, so no L2 write-back or invalidate is
emitted. The GFX942 workgroup release waits lgkmcnt(0) only outside
tgsplit mode, so a publishing CTA also has every wave wait for its own stores
before the barrier (cta_sync(drain=True)). The step-end fault handshake
uses plain system release / acquire once a step.
A poll gives up after ticks of the 100 MHz clock or once any rank has set
the error word; a timeout sets [1, rank, epoch, site] on every rank.
Classes:
-
Mailbox–Tagged pairs of one launch (
tag), every address anAddr.
Functions:
-
cta_sync–gpu.barrier: workgroup release fence,s_barrier, acquire fence -
load128–Dwords i .. i + 3 (i a multiple of 4): one load-visible at
scope. -
load_dev–Dwords i .. i + n of this GPU's scratch (n in {1, 2, 4}, i aligned),
-
store_dev–Dwords i .. of this GPU's scratch :=
words(1 or 2, i aligned), -
wave_sync–Every lane of the wave: what each lane did before (its acquires)
Mailbox
¶
Tagged pairs of one launch (tag), every address an Addr.
Methods:
-
acquire–After a poll of published pairs, before what they announce.
-
poll–Pairs
specs= [(Addr, pair index, npairs in {1, 2})], all of one -
publish–Pair i of
a:= (v, tag) after a synchronizing release: what -
put–Pair i of
a:= (v, tag), monotonic: a value no other data hangs on. -
put_release_all–Pair i of every
addrs:= (v, tag) after one release fence. -
put_triple–Pair i of
a:= (48 value bits | tag16 << 48), monotonic.
Source code in vllm/models/minimax_m3/amd/specialized_decode/mono/sync.py
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 | |
acquire(space)
¶
poll(specs, batch=POLL_MAX, site=0, triples=False)
¶
Pairs specs = [(Addr, pair index, npairs in {1, 2})], all of one
space, re-loaded together until every tag is this launch's. Returns the
value words; triples: of triple pairs (put_triple), both
words.
Source code in vllm/models/minimax_m3/amd/specialized_decode/mono/sync.py
publish(a, i, v)
¶
Pair i of a := (v, tag) after a synchronizing release: what
happened before it (the CTA's stores past a cta_sync(drain=True),
pairs it acquired) happens before an acquire of the pair.
Source code in vllm/models/minimax_m3/amd/specialized_decode/mono/sync.py
put(a, i, v)
¶
Pair i of a := (v, tag), monotonic: a value no other data hangs on.
Source code in vllm/models/minimax_m3/amd/specialized_decode/mono/sync.py
put_release_all(addrs, i, v)
¶
Pair i of every addrs := (v, tag) after one release fence.
put_triple(a, i, bits48)
¶
Pair i of a := (48 value bits | tag16 << 48), monotonic.
_ptr(addr, i, bits=64)
¶
The global pointer to element i (of bits) of address addr.
Source code in vllm/models/minimax_m3/amd/specialized_decode/mono/sync.py
_sync_fence(ordering, scope)
¶
A fence that synchronizes without making anything available or visible.
Source code in vllm/models/minimax_m3/amd/specialized_decode/mono/sync.py
cta_sync(drain=False)
¶
gpu.barrier: workgroup release fence, s_barrier, acquire fence
(HIP's __syncthreads). drain: every wave's stores complete first.
Source code in vllm/models/minimax_m3/amd/specialized_decode/mono/sync.py
load128(addr, i, scope)
¶
Dwords i .. i + 3 (i a multiple of 4): one load-visible at scope.
Source code in vllm/models/minimax_m3/amd/specialized_decode/mono/sync.py
load_dev(addr, i, n=1)
¶
Dwords i .. i + n of this GPU's scratch (n in {1, 2, 4}, i aligned), load-visible at agent scope.
Source code in vllm/models/minimax_m3/amd/specialized_decode/mono/sync.py
store_dev(addr, i, words)
¶
Dwords i .. of this GPU's scratch := words (1 or 2, i aligned),
store-available at agent scope.
Source code in vllm/models/minimax_m3/amd/specialized_decode/mono/sync.py
wave_sync(count, target)
¶
Every lane of the wave: what each lane did before (its acquires)
happens before what any lane does after. Each lane releases, adds one to
the wave's LDS count, and acquires once it reads target; the read
value comes after every lane's add in the counter's order (a release
sequence), so it synchronizes with every lane's release.