Files
TheRock/rocm-systems/docs/superpowers/specs/2026-07-24-msc-atomic-alias-coherence-design.md
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

4.1 KiB

MSC Atomic Alias Coherence Design

Context

L2Cache::atomic_rmw acquires the device-wide atomic boundary before accessing backing memory. The boundary flushes every registered L2 and then advances the global coherence epoch while holding the L2 maintenance locks.

The direct-memory path therefore observes the flushed value. The linked-port path instead reads through MemorySideCache (MSC). MSC is write-through and keys clean cache lines by (VMID, GPU virtual address). If two such keys alias the same host storage, a clean line under one key can remain stale after another key publishes dirty L2 data. An atomic RMW through the stale key can consequently use the old value.

Goals

  • Make linked-port atomic RMWs observe the authoritative value after all L2 dirty data has been published.
  • Ensure stale MSC aliases are not visible after a coherence epoch change.
  • Preserve the existing device-wide atomic serialization and L2 locking model.
  • Avoid scanning or invalidating the entire 128 MiB MSC on every atomic.
  • Add regression coverage for two L2s sharing one MSC and HBM through aliased VMID/virtual-address mappings.
  • Remove the unused register_cache helper so there is one L2 registration implementation and one ordering invariant.

Design

Each MSC cache tag will record the device-coherence epoch at which its line was filled or refreshed. MSC already protects tag lookup and replacement with the corresponding stripe lock, so the epoch metadata will use that same protection.

On an MSC access:

  1. Look up the (VMID, GPU virtual address) cache line under its stripe lock.
  2. Compare the tag's recorded epoch with DeviceCacheCoherence::current_epoch().
  3. If the epochs differ, require the old entry to be clean, invalidate it, and refill the line from backing HBM.
  4. Stamp a newly filled or refreshed entry with the current epoch.
  5. Continue the requested read or write.

The atomic boundary's existing order remains unchanged:

  1. Acquire the global exclusive coherence lock.
  2. Lock every registered L2 maintenance mutex in sorted address order.
  3. Flush dirty L2 data through MSC to HBM.
  4. Advance the global coherence epoch.
  5. Perform the linked-port RMW while the boundary remains held.

After step 4, any MSC alias retained from an earlier epoch is stale. The RMW read therefore invalidates and refills that alias from HBM, where step 3 published the authoritative value. Other old aliases are invalidated lazily on their next access.

MSC is write-through, so an epoch-stale entry is expected to be clean and can be discarded without losing data. No MSC registration or new global lock is needed.

Alternatives

Eagerly flush and invalidate the entire MSC

Registering MSC with the atomic boundary and calling flush_all() would be simple, but it scans 1,048,576 tags and locks all 256 stripes for every atomic. That cost is disproportionate to an individual RMW.

Bypass MSC only for atomic backing accesses

Sending the RMW directly to HBM would obtain the correct operand, but clean MSC aliases could remain stale and be returned after the atomic. A generation or invalidation mechanism would still be required, while the backing protocol would become more complex.

Validation

Add a regression with two L2 caches linked to one MSC and HBM controller:

  1. Map different (VMID, GPU virtual address) pairs to the same host word.
  2. Read through the second alias to retain a clean MSC value of 0.
  3. Dirty 40 through the first L2 without immediately publishing it.
  4. Increment through the second L2's atomic RMW.
  5. Verify the callback observes 40, the atomic result and host word are 41, and subsequent reads through both aliases return 41.

Run the focused L2/MSC tests in Release and under TSan, followed by the relevant non-benchmark test suite.

Measure end-to-end performance against commit b685943638 using representative large kernels from rocjitsu-test-corpus, including a large softmax, a large pack/unpack case, and a large matrix multiplication. Use the same pinned-CPU, alternating-run methodology as the previously published PR benchmark where the harness permits it.