pantheon-gpu 1.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. pantheon_gpu/Makefile +207 -0
  2. pantheon_gpu/VERSION +1 -0
  3. pantheon_gpu/__init__.py +1 -0
  4. pantheon_gpu/_entry.py +17 -0
  5. pantheon_gpu/kernels/all_reduce/README.md +17 -0
  6. pantheon_gpu/kernels/all_reduce/all_reduce.cpp +178 -0
  7. pantheon_gpu/kernels/allocation_fragmentation/README.md +3 -0
  8. pantheon_gpu/kernels/allocation_fragmentation/allocation_fragmentation.cpp +177 -0
  9. pantheon_gpu/kernels/atomic_virus/README.md +57 -0
  10. pantheon_gpu/kernels/atomic_virus/atomic_virus.cpp +266 -0
  11. pantheon_gpu/kernels/atomic_virus/atomic_virus_flow.svg +33 -0
  12. pantheon_gpu/kernels/cache_latency/README.md +57 -0
  13. pantheon_gpu/kernels/cache_latency/cache_latency.cpp +279 -0
  14. pantheon_gpu/kernels/cache_latency/cache_latency_flow.svg +30 -0
  15. pantheon_gpu/kernels/common/ai_workload_template.h +366 -0
  16. pantheon_gpu/kernels/common/common.h +427 -0
  17. pantheon_gpu/kernels/common/fault_log.h +136 -0
  18. pantheon_gpu/kernels/common/fp16_shim.h +20 -0
  19. pantheon_gpu/kernels/common/mock_gpu.h +212 -0
  20. pantheon_gpu/kernels/common/nvenc/nvEncodeAPI.h +4667 -0
  21. pantheon_gpu/kernels/compute_virus/README.md +59 -0
  22. pantheon_gpu/kernels/compute_virus/compute_virus.cpp +223 -0
  23. pantheon_gpu/kernels/compute_virus/compute_virus_agg.cpp +280 -0
  24. pantheon_gpu/kernels/compute_virus/compute_virus_flow.svg +36 -0
  25. pantheon_gpu/kernels/fp64_virus/README.md +96 -0
  26. pantheon_gpu/kernels/fp64_virus/fp64_virus.cpp +249 -0
  27. pantheon_gpu/kernels/fp64_virus/fp64_virus_flow.svg +95 -0
  28. pantheon_gpu/kernels/fused_attention/README.md +3 -0
  29. pantheon_gpu/kernels/fused_attention/fused_attention.cpp +2 -0
  30. pantheon_gpu/kernels/galpat/README.md +62 -0
  31. pantheon_gpu/kernels/galpat/galpat.cpp +233 -0
  32. pantheon_gpu/kernels/graph_replay/README.md +3 -0
  33. pantheon_gpu/kernels/graph_replay/graph_replay.cpp +173 -0
  34. pantheon_gpu/kernels/idle/README.md +34 -0
  35. pantheon_gpu/kernels/idle/idle.cpp +29 -0
  36. pantheon_gpu/kernels/idle/idle_flow.svg +11 -0
  37. pantheon_gpu/kernels/int_virus/README.md +57 -0
  38. pantheon_gpu/kernels/int_virus/int_virus.cpp +272 -0
  39. pantheon_gpu/kernels/int_virus/int_virus_flow.svg +32 -0
  40. pantheon_gpu/kernels/kv_cache_churn/README.md +20 -0
  41. pantheon_gpu/kernels/kv_cache_churn/kv_cache_churn.cpp +37 -0
  42. pantheon_gpu/kernels/llm_decode/README.md +25 -0
  43. pantheon_gpu/kernels/llm_decode/llm_decode.cpp +113 -0
  44. pantheon_gpu/kernels/llm_prefill/README.md +22 -0
  45. pantheon_gpu/kernels/llm_prefill/llm_prefill.cpp +55 -0
  46. pantheon_gpu/kernels/march_test/README.md +72 -0
  47. pantheon_gpu/kernels/march_test/march_test.cpp +243 -0
  48. pantheon_gpu/kernels/media_enc_virus/README.md +38 -0
  49. pantheon_gpu/kernels/media_enc_virus/media_enc_virus.cpp +267 -0
  50. pantheon_gpu/kernels/media_enc_virus/media_enc_virus_flow.svg +10 -0
  51. pantheon_gpu/kernels/memory_bank_thrash/README.md +42 -0
  52. pantheon_gpu/kernels/memory_bank_thrash/memory_bank_thrash.cpp +228 -0
  53. pantheon_gpu/kernels/memory_bank_thrash/memory_bank_thrash_flow.svg +10 -0
  54. pantheon_gpu/kernels/memory_cache_fracture/README.md +42 -0
  55. pantheon_gpu/kernels/memory_cache_fracture/memory_cache_fracture.cpp +223 -0
  56. pantheon_gpu/kernels/memory_cache_fracture/memory_cache_fracture_flow.svg +9 -0
  57. pantheon_gpu/kernels/memory_hammer/README.md +83 -0
  58. pantheon_gpu/kernels/memory_hammer/memory_hammer.cpp +299 -0
  59. pantheon_gpu/kernels/memory_pc_pingpong/README.md +42 -0
  60. pantheon_gpu/kernels/memory_pc_pingpong/memory_pc_pingpong.cpp +248 -0
  61. pantheon_gpu/kernels/memory_pc_pingpong/memory_pc_pingpong_flow.svg +9 -0
  62. pantheon_gpu/kernels/memory_read/README.md +69 -0
  63. pantheon_gpu/kernels/memory_read/memory_read.cpp +295 -0
  64. pantheon_gpu/kernels/memory_retention/README.md +67 -0
  65. pantheon_gpu/kernels/memory_retention/memory_retention.cpp +193 -0
  66. pantheon_gpu/kernels/memory_retention_bake/README.md +41 -0
  67. pantheon_gpu/kernels/memory_retention_bake/memory_retention_bake.cpp +245 -0
  68. pantheon_gpu/kernels/memory_retention_bake/memory_retention_bake_flow.svg +10 -0
  69. pantheon_gpu/kernels/memory_thermal_asym/README.md +41 -0
  70. pantheon_gpu/kernels/memory_thermal_asym/memory_thermal_asym.cpp +230 -0
  71. pantheon_gpu/kernels/memory_thermal_asym/memory_thermal_asym_flow.svg +7 -0
  72. pantheon_gpu/kernels/memory_tsv_thrasher/README.md +42 -0
  73. pantheon_gpu/kernels/memory_tsv_thrasher/memory_tsv_thrasher.cpp +242 -0
  74. pantheon_gpu/kernels/memory_tsv_thrasher/memory_tsv_thrasher_flow.svg +8 -0
  75. pantheon_gpu/kernels/memory_write/README.md +71 -0
  76. pantheon_gpu/kernels/memory_write/memory_write.cpp +262 -0
  77. pantheon_gpu/kernels/mma_virus/README.md +42 -0
  78. pantheon_gpu/kernels/mma_virus/mma_virus.cpp +288 -0
  79. pantheon_gpu/kernels/mma_virus/mma_virus_flow.svg +10 -0
  80. pantheon_gpu/kernels/moe_router/README.md +3 -0
  81. pantheon_gpu/kernels/moe_router/moe_router.cpp +2 -0
  82. pantheon_gpu/kernels/omni_virus/README.md +43 -0
  83. pantheon_gpu/kernels/omni_virus/omni_virus.cpp +375 -0
  84. pantheon_gpu/kernels/omni_virus/omni_virus_flow.svg +7 -0
  85. pantheon_gpu/kernels/p2p_thrasher/README.md +57 -0
  86. pantheon_gpu/kernels/p2p_thrasher/p2p_thrasher.cpp +280 -0
  87. pantheon_gpu/kernels/p2p_thrasher/p2p_thrasher_flow.svg +27 -0
  88. pantheon_gpu/kernels/pcie_bandwidth/README.md +56 -0
  89. pantheon_gpu/kernels/pcie_bandwidth/pcie_bandwidth.cpp +284 -0
  90. pantheon_gpu/kernels/pcie_bandwidth/pcie_bandwidth_flow.svg +19 -0
  91. pantheon_gpu/kernels/pulse_virus/README.md +56 -0
  92. pantheon_gpu/kernels/pulse_virus/pulse_virus.cpp +256 -0
  93. pantheon_gpu/kernels/pulse_virus/pulse_virus_flow.svg +18 -0
  94. pantheon_gpu/kernels/quantized_gemm/README.md +3 -0
  95. pantheon_gpu/kernels/quantized_gemm/quantized_gemm.cpp +2 -0
  96. pantheon_gpu/kernels/rag_embedding/README.md +3 -0
  97. pantheon_gpu/kernels/rag_embedding/rag_embedding.cpp +2 -0
  98. pantheon_gpu/kernels/ras_validator/README.md +41 -0
  99. pantheon_gpu/kernels/ras_validator/ras_validator.cpp +270 -0
  100. pantheon_gpu/kernels/ras_validator/ras_validator_flow.svg +10 -0
  101. pantheon_gpu/kernels/rope_stress/README.md +3 -0
  102. pantheon_gpu/kernels/rope_stress/rope_stress.cpp +2 -0
  103. pantheon_gpu/kernels/rt_virus/README.md +56 -0
  104. pantheon_gpu/kernels/rt_virus/rt_virus.cpp +567 -0
  105. pantheon_gpu/kernels/rt_virus/rt_virus_flow.svg +20 -0
  106. pantheon_gpu/kernels/scheduler_virus/README.md +42 -0
  107. pantheon_gpu/kernels/scheduler_virus/scheduler_virus.cpp +260 -0
  108. pantheon_gpu/kernels/scheduler_virus/scheduler_virus_flow.svg +9 -0
  109. pantheon_gpu/kernels/serving_mix/README.md +3 -0
  110. pantheon_gpu/kernels/serving_mix/serving_mix.cpp +2 -0
  111. pantheon_gpu/kernels/sfu_stress/README.md +57 -0
  112. pantheon_gpu/kernels/sfu_stress/sfu_stress.cpp +246 -0
  113. pantheon_gpu/kernels/sfu_stress/sfu_stress_flow.svg +31 -0
  114. pantheon_gpu/kernels/speculative_decode/README.md +3 -0
  115. pantheon_gpu/kernels/speculative_decode/speculative_decode.cpp +2 -0
  116. pantheon_gpu/kernels/tensor_virus/README.md +56 -0
  117. pantheon_gpu/kernels/tensor_virus/tensor_virus.cpp +251 -0
  118. pantheon_gpu/kernels/tensor_virus/tensor_virus_flow.svg +29 -0
  119. pantheon_gpu/kernels/tlb_avalanche/README.md +57 -0
  120. pantheon_gpu/kernels/tlb_avalanche/tlb_avalanche.cpp +295 -0
  121. pantheon_gpu/kernels/tlb_avalanche/tlb_avalanche_flow.svg +35 -0
  122. pantheon_gpu/kernels/transformer_train_step/README.md +3 -0
  123. pantheon_gpu/kernels/transformer_train_step/transformer_train_step.cpp +2 -0
  124. pantheon_gpu/kernels/transformer_virus/README.md +43 -0
  125. pantheon_gpu/kernels/transformer_virus/transformer_virus.cpp +393 -0
  126. pantheon_gpu/kernels/transformer_virus/transformer_virus_flow.svg +10 -0
  127. pantheon_gpu/kernels/vision_encoder/README.md +3 -0
  128. pantheon_gpu/kernels/vision_encoder/vision_encoder.cpp +2 -0
  129. pantheon_gpu/monitor.py +417 -0
  130. pantheon_gpu/pantheon.py +2572 -0
  131. pantheon_gpu-1.2.0.dist-info/METADATA +270 -0
  132. pantheon_gpu-1.2.0.dist-info/RECORD +137 -0
  133. pantheon_gpu-1.2.0.dist-info/WHEEL +5 -0
  134. pantheon_gpu-1.2.0.dist-info/entry_points.txt +3 -0
  135. pantheon_gpu-1.2.0.dist-info/licenses/LICENSE +201 -0
  136. pantheon_gpu-1.2.0.dist-info/licenses/NOTICE +42 -0
  137. pantheon_gpu-1.2.0.dist-info/top_level.txt +1 -0
pantheon_gpu/Makefile ADDED
@@ -0,0 +1,207 @@
1
+ # PANTHEON Build System
2
+
3
+ # --- Compiler Configuration ---
4
+ HIPCC ?= hipcc
5
+ CXXFLAGS := -O3 -std=c++14 -DNDEBUG -Ikernels/common
6
+ BUILD_DIR := build
7
+ ROCM_PATH ?= /opt/rocm
8
+ BUILD_STAMP := $(BUILD_DIR)/.platform
9
+
10
+ # Platform Detection
11
+ ifeq ($(PLATFORM), MOCK)
12
+ COMPILER := g++
13
+ # Enable Mock Flag and suppress warnings about GPU-specific pragmas
14
+ CXXFLAGS += -DPANTHEON_MOCK -Wno-unknown-pragmas -pthread
15
+
16
+ else ifeq ($(PLATFORM), CUDA)
17
+ COMPILER := nvcc
18
+
19
+ # 1. Detect physical GPU architecture
20
+ # nvidia-smi writes "NVIDIA-SMI has failed because it couldn't communicate
21
+ # with the NVIDIA driver" to STDOUT, so 2>/dev/null does not suppress it.
22
+ # Without the numeric filter that sentence becomes DETECTED_ARCH: it is
23
+ # non-empty, so the failsafe below never fires, and it reaches the compiler
24
+ # as sm_<sentence> -- whose apostrophe breaks shell quoting, producing
25
+ # "/bin/sh: Syntax error: Unterminated quoted string" instead of the
26
+ # readable fallback this block was written to provide.
27
+ DETECTED_ARCH := $(strip $(shell nvidia-smi --query-gpu=compute_cap --format=csv,noheader 2>/dev/null | head -n 1 | tr -d '.' | grep -E '^[0-9]+$$'))
28
+ # Print it immediately during the parsing phase
29
+ $(info [DEBUG] The detected architecture is: $(DETECTED_ARCH))
30
+
31
+ # 2. Hopper WGMMA Promotion
32
+ # Hopper requires the 'a' suffix (sm_90a) to unlock WGMMA PTX instructions
33
+ ifeq ($(DETECTED_ARCH), 90)
34
+ DETECTED_ARCH := 90a
35
+ endif
36
+
37
+ # 3. The Ultimate Failsafe
38
+ # If nvidia-smi fails (e.g., compiling on a CPU-only login node),
39
+ # default to Hopper (90a) so the build doesn't crash with an empty 'sm_' flag.
40
+ ifeq ($(DETECTED_ARCH),)
41
+ $(info [DEBUG] Hardware detection failed. Falling back to default sm_86...)
42
+ DETECTED_ARCH := 86
43
+ endif
44
+
45
+ # --- Vendored Headers ---
46
+ # OptiX headers are NVIDIA-proprietary and are not redistributable, so this
47
+ # tree does not require them. Set OPTIX_PATH to an OptiX SDK include
48
+ # directory to build the real RT kernel; otherwise rt_virus builds its dummy
49
+ # kernel, exactly as it already does when HIP-RT is missing on AMD.
50
+ OPTIX_PATH ?= $(wildcard kernels/common/optix)
51
+ ifneq ($(OPTIX_PATH),)
52
+ OPTIX_INC := -I $(OPTIX_PATH)
53
+ else
54
+ OPTIX_INC :=
55
+ $(info [DEBUG] OptiX headers not found; rt_virus will build its dummy kernel. Set OPTIX_PATH to enable it.)
56
+ endif
57
+ NVENC_INC := -I kernels/common/nvenc
58
+
59
+ CXXFLAGS += -x cu --gpu-architecture=sm_$(DETECTED_ARCH) -Wno-deprecated-gpu-targets $(OPTIX_INC) $(NVENC_INC)
60
+
61
+ # --- Link the CUDA Driver API and Dynamic Loader ---
62
+ LDFLAGS += -lcuda -ldl
63
+
64
+ else
65
+ COMPILER := $(HIPCC)
66
+
67
+ # 1. Detect physical GPU architecture (Modern ROCm uses amdgpu-arch)
68
+ DETECTED_GFX := $(strip $(shell amdgpu-arch 2>/dev/null | head -n 1))
69
+ ifeq ($(DETECTED_GFX),)
70
+ DETECTED_GFX := $(strip $(shell rocm_agent_enumerator 2>/dev/null | grep -v "cpu" | head -n 1))
71
+ endif
72
+
73
+ # 2. Manual Override & Failsafe
74
+ # Allows cross-compiling on CPU nodes via: make PLATFORM=HIP TARGET_GFX=gfx950
75
+ ifdef TARGET_GFX
76
+ DETECTED_GFX := $(TARGET_GFX)
77
+ endif
78
+
79
+ # Tool output can include feature suffixes such as gfx90a:sramecc+:xnack-.
80
+ # hipcc's --offload-arch expects the architecture name only.
81
+ DETECTED_GFX := $(firstword $(subst :, ,$(DETECTED_GFX)))
82
+
83
+ ifeq ($(DETECTED_GFX),)
84
+ $(info [DEBUG] Hardware detection failed. Falling back to MI300X default...)
85
+ DETECTED_GFX := gfx942
86
+ endif
87
+
88
+ $(info [DEBUG] The AMD target architecture is: $(DETECTED_GFX))
89
+
90
+ # RDNA-family parts (gfx11xx, gfx12xx) provide WMMA; CDNA Instinct parts
91
+ # provide MFMA. Match on the two-digit family prefix rather than on
92
+ # individual model numbers, so any member of a family -- including ones
93
+ # that do not exist yet -- selects the right path with no source change.
94
+ GFX_FAMILY := $(shell printf '%s' '$(DETECTED_GFX)' | sed -E 's/^(gfx[0-9]{2}).*/\1/')
95
+ ifneq ($(filter gfx11 gfx12,$(GFX_FAMILY)),)
96
+ CXXFLAGS += -DPANTHEON_AMD_WMMA_TARGET=1
97
+ $(info [DEBUG] WMMA-capable family detected ($(GFX_FAMILY)); enabling WMMA path.)
98
+ endif
99
+
100
+ # 3. FIX: Force Native Compilation for Pantheon Kernels
101
+ # If a specific cross-compile target wasn't requested, trust the compiler to
102
+ # generate machine code for the exact silicon it is currently sitting on.
103
+ # This completely prevents Code 98 on bleeding-edge chips like the MI350X.
104
+ ifdef TARGET_GFX
105
+ CXXFLAGS += -std=c++17 --offload-arch=$(DETECTED_GFX)
106
+ else
107
+ CXXFLAGS += -std=c++17 --offload-arch=native
108
+ endif
109
+
110
+ # --- Optional Local HIP-RT Vendoring ---
111
+ # The RT kernel builds a dummy fallback when HIP-RT headers are absent, so
112
+ # do not make every AMD build clone and compile HIP-RT by default.
113
+ VENDOR_DIR := vendor
114
+ HIPRT_DIR := $(VENDOR_DIR)/HIPRT
115
+ HIPRT_INSTALL := $(VENDOR_DIR)/install
116
+ HIPRT_TARGET := $(HIPRT_INSTALL)/lib/libhiprt64.so
117
+
118
+ ifeq ($(ENABLE_HIPRT),1)
119
+ CXXFLAGS += -I$(abspath $(HIPRT_INSTALL)/include)
120
+ LDFLAGS += -L$(abspath $(HIPRT_INSTALL)/lib) -lhiprt64 -Wl,-rpath=$(abspath $(HIPRT_INSTALL)/lib)
121
+ PLATFORM_DEPS := $(HIPRT_TARGET)
122
+ endif
123
+ endif
124
+
125
+ # OPTIX_PATH is part of the signature: setting it after a build without it
126
+ # must invalidate the cached binaries, or rt_virus silently keeps running the
127
+ # dummy kernel it compiled when the headers were absent.
128
+ BUILD_SIGNATURE := PLATFORM=$(PLATFORM);CUDA_ARCH=$(DETECTED_ARCH);AMD_GFX=$(DETECTED_GFX);TARGET_GFX=$(DETECTED_GFX);ENABLE_HIPRT=$(ENABLE_HIPRT);OPTIX=$(OPTIX_PATH)
129
+
130
+ # --- Auto-Discovery Logic ---
131
+
132
+ # 1. Find all .cpp files inside kernels/ subdirectories
133
+ ALL_SRCS := $(shell find kernels -name "*.cpp")
134
+
135
+ # 2. Exclude anything in the 'common' directory or root headers
136
+ SRCS := $(filter-out kernels/common/%, $(ALL_SRCS))
137
+
138
+ # Empty discovery means find is unavailable (minimal container images such as
139
+ # rockylinux:8 omit findutils) or the kernels tree is missing. Without this
140
+ # guard make exits 0 having built nothing and every workload fails at launch.
141
+ ifeq ($(strip $(SRCS)),)
142
+ $(error No kernel sources found under kernels/. Verify that 'find' is installed and the kernels/ directory exists)
143
+ endif
144
+
145
+ # 3. Determine Target Binaries
146
+ BINS := $(foreach src,$(SRCS),$(BUILD_DIR)/$(basename $(notdir $(src))))
147
+
148
+ # Shared headers included by many kernel translation units.
149
+ COMMON_HEADERS := kernels/common/common.h kernels/common/ai_workload_template.h
150
+
151
+ # --- Targets ---
152
+
153
+ .PHONY: all clean directories FORCE
154
+
155
+ # Add PLATFORM_DEPS here so HIP-RT is built before the binaries
156
+ all: directories $(BUILD_STAMP) $(PLATFORM_DEPS) $(BINS)
157
+
158
+ $(BUILD_STAMP): FORCE | directories
159
+ @if [ ! -f "$@" ] || [ "$$(cat "$@")" != "$(BUILD_SIGNATURE)" ]; then \
160
+ echo "[BUILD] Platform signature changed. Clearing stale binaries..."; \
161
+ find $(BUILD_DIR) -maxdepth 1 -type f ! -name ".platform" -delete; \
162
+ printf '%s\n' '$(BUILD_SIGNATURE)' > "$@"; \
163
+ fi
164
+
165
+ $(BINS): $(BUILD_STAMP)
166
+
167
+ # --- Auto-Dependency: HIP-RT ---
168
+ $(HIPRT_TARGET):
169
+ @echo "============================================================"
170
+ @echo "[DEPENDENCY] Fetching and building HIP-RT locally..."
171
+ @echo "============================================================"
172
+ @mkdir -p $(VENDOR_DIR)
173
+ @if [ ! -d "$(HIPRT_DIR)" ]; then \
174
+ git clone https://github.com/GPUOpen-LibrariesAndSDKs/HIPRT.git $(HIPRT_DIR); \
175
+ cd $(HIPRT_DIR) && git submodule update --init --recursive; \
176
+ fi
177
+ @echo "[DEPENDENCY] Injecting $(DETECTED_GFX) architecture into AMD build scripts..."
178
+ @find $(HIPRT_DIR) -type f \( -name "*.py" -o -name "CMakeLists.txt" \) -exec sed -i "s/'gfx942'/'gfx942', '$(DETECTED_GFX)'/g" {} +
179
+ @find $(HIPRT_DIR) -type f \( -name "*.py" -o -name "CMakeLists.txt" \) -exec sed -i 's/"gfx942"/"gfx942", "$(DETECTED_GFX)"/g' {} +
180
+ @find $(HIPRT_DIR) -type f -name "CMakeLists.txt" -exec sed -i 's/gfx942/gfx942;$(DETECTED_GFX)/g' {} +
181
+ @mkdir -p $(HIPRT_DIR)/build
182
+ @cd $(HIPRT_DIR)/build && cmake -DCMAKE_BUILD_TYPE=Release -DBITCODE=ON -DPRECOMPILE=ON -DFORCE_DISABLE_CUDA=ON -DHIP_PATH=$(ROCM_PATH) -DPYTHON_EXECUTABLE=/usr/bin/python3 -DAMDGPU_TARGETS=$(DETECTED_GFX) -DGPU_TARGETS=$(DETECTED_GFX) ..
183
+ @cd $(HIPRT_DIR)/build && cmake --build . --config Release -j $$(nproc)
184
+ @echo "[DEPENDENCY] Build finished. Extracting all runtime assets..."
185
+ @mkdir -p $(HIPRT_INSTALL)/lib
186
+ @mkdir -p $(HIPRT_INSTALL)/include
187
+ @find $(HIPRT_DIR) -type f \( -name "*.hipfb" -o -name "*.bc" -o -name "libhiprt*64.so*" \) -exec cp -L {} $(HIPRT_INSTALL)/lib/ \;
188
+ @REAL_SO=$$(find $(HIPRT_INSTALL)/lib -name "libhiprt*64.so*" -type f | head -n 1); \
189
+ ln -sf $$(basename $$REAL_SO) $(HIPRT_INSTALL)/lib/libhiprt64.so
190
+ @cp -r $(HIPRT_DIR)/hiprt $(HIPRT_INSTALL)/include/
191
+ @echo "[DEPENDENCY] HIP-RT and Orochi assets successfully installed to local vendor folder!"
192
+
193
+ # Create build directory
194
+ directories:
195
+ @mkdir -p $(BUILD_DIR)
196
+
197
+ # Generic Rule: Build any binary from its corresponding source found in kernels tree
198
+ vpath %.cpp $(sort $(dir $(SRCS)))
199
+
200
+ $(BUILD_DIR)/%: %.cpp $(COMMON_HEADERS) $(BUILD_STAMP)
201
+ @echo "[BUILD] Compiling $< -> $@"
202
+ @$(COMPILER) $(CXXFLAGS) $< -o $@ $(LDFLAGS)
203
+
204
+ clean:
205
+ @echo "[CLEAN] Removing build artifacts..."
206
+ @rm -rf $(BUILD_DIR)
207
+ @rm -rf $(VENDOR_DIR)
pantheon_gpu/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.2.0
@@ -0,0 +1 @@
1
+ """Pantheon GPU stress and diagnostics suite."""
pantheon_gpu/_entry.py ADDED
@@ -0,0 +1,17 @@
1
+ """Console entry point for an installed Pantheon."""
2
+
3
+ import os
4
+
5
+
6
+ def main():
7
+ # site-packages is not writable, and the runner defaults to building
8
+ # beside its own source unless told otherwise. Respect an explicit
9
+ # override so a user can still choose the location.
10
+ if not os.environ.get("PANTHEON_BUILD_CACHE_DIR", "").strip():
11
+ cache = os.environ.get("XDG_CACHE_HOME", "").strip() or os.path.join(
12
+ os.path.expanduser("~"), ".cache")
13
+ os.environ["PANTHEON_BUILD_CACHE_DIR"] = os.path.join(
14
+ cache, "pantheongpu", "builds")
15
+
16
+ from . import pantheon
17
+ return pantheon.main()
@@ -0,0 +1,17 @@
1
+ # All-Reduce
2
+
3
+ `all_reduce` is a two-rank GPU collective. It initializes one rank with `1`
4
+ and the other with `2`, sums them on the primary GPU, then broadcasts the
5
+ resulting `3` back to both ranks. `--verify` checks both GPU buffers.
6
+
7
+ Pantheon uses direct peer DMA when bidirectional peer access is available. If
8
+ the topology does not expose peer access, it reports a host-staged fallback
9
+ instead. The fallback validates correctness but should not be used as a direct
10
+ P2P bandwidth measurement.
11
+
12
+ ```bash
13
+ pantheon --test all_reduce --duration 60 --gpu 0 --verify --profile
14
+ ```
15
+
16
+ Use `--inject_error --verify` to confirm that verification detects a corrupted
17
+ value on the peer rank.
@@ -0,0 +1,178 @@
1
+ #include "../common/common.h"
2
+
3
+ #include <chrono>
4
+ #include <iostream>
5
+ #include <string>
6
+
7
+ // A real two-rank all-reduce. GPU 1's input is copied to GPU 0, reduced
8
+ // there, then the completed value is broadcast back to GPU 1.
9
+ __global__ void init_collective(unsigned int* data, size_t count, unsigned int value) {
10
+ size_t idx = blockIdx.x * blockDim.x + threadIdx.x;
11
+ size_t stride = blockDim.x * gridDim.x;
12
+ for (; idx < count; idx += stride) data[idx] = value;
13
+ }
14
+
15
+ __global__ void add_collective(unsigned int* dst, const unsigned int* src, size_t count) {
16
+ size_t idx = blockIdx.x * blockDim.x + threadIdx.x;
17
+ size_t stride = blockDim.x * gridDim.x;
18
+ for (; idx < count; idx += stride) dst[idx] += src[idx];
19
+ }
20
+
21
+ __global__ void corrupt_collective(unsigned int* data) {
22
+ if (blockIdx.x == 0 && threadIdx.x == 0) data[0] ^= 1u;
23
+ }
24
+
25
+ __global__ void verify_collective(const unsigned int* data, size_t count, unsigned int expected, unsigned int* errors) {
26
+ size_t idx = blockIdx.x * blockDim.x + threadIdx.x;
27
+ size_t stride = blockDim.x * gridDim.x;
28
+ for (; idx < count; idx += stride) if (data[idx] != expected) atomicAdd(errors, 1);
29
+ }
30
+
31
+ int main(int argc, char** argv) {
32
+ if (argc < 4) return 1;
33
+ int primary = atoi(argv[1]);
34
+ int duration = atoi(argv[2]);
35
+ bool verify = false;
36
+ bool inject_error = false;
37
+ for (int i = 1; i < argc; ++i) {
38
+ std::string arg(argv[i]);
39
+ if (arg == "--verify") verify = true;
40
+ else if (arg == "--inject_error") inject_error = true;
41
+ }
42
+
43
+ int devices = 0;
44
+ CHECK(hipGetDeviceCount(&devices));
45
+ if (devices < 2) {
46
+ std::cout << "[PANTHEON] Skipping ALL_REDUCE: fewer than two GPUs." << std::endl;
47
+ std::cout << "Throughput: 0.0 GB/s" << std::endl;
48
+ return 0;
49
+ }
50
+
51
+ int peer = (primary + 1) % devices;
52
+ int forward_peer_access = 0;
53
+ int reverse_peer_access = 0;
54
+ CHECK(hipDeviceCanAccessPeer(&forward_peer_access, primary, peer));
55
+ CHECK(hipDeviceCanAccessPeer(&reverse_peer_access, peer, primary));
56
+ bool p2p = forward_peer_access && reverse_peer_access;
57
+ if (p2p) {
58
+ CHECK(hipSetDevice(primary));
59
+ CHECK(hipDeviceEnablePeerAccess(peer, 0));
60
+ CHECK(hipSetDevice(peer));
61
+ CHECK(hipDeviceEnablePeerAccess(primary, 0));
62
+ }
63
+
64
+ const size_t bytes = 64ull * 1024 * 1024;
65
+ const size_t count = bytes / sizeof(unsigned int);
66
+ const int blocks = 4096;
67
+ unsigned int* primary_data = nullptr;
68
+ unsigned int* peer_data = nullptr;
69
+ unsigned int* scratch = nullptr;
70
+ void* host_stage = nullptr;
71
+
72
+ CHECK(hipSetDevice(primary));
73
+ CHECK(hipMalloc(&primary_data, bytes));
74
+ CHECK(hipMalloc(&scratch, bytes));
75
+ if (!p2p) CHECK(hipHostMalloc(&host_stage, bytes));
76
+ CHECK(hipSetDevice(peer));
77
+ CHECK(hipMalloc(&peer_data, bytes));
78
+ CHECK(hipSetDevice(primary));
79
+ hipStream_t stream;
80
+ CHECK(hipStreamCreate(&stream));
81
+
82
+ LAUNCH_KERNEL(init_collective, blocks, 256, primary_data, count, 1u);
83
+ CHECK(hipSetDevice(peer));
84
+ LAUNCH_KERNEL(init_collective, blocks, 256, peer_data, count, 2u);
85
+ CHECK(hipDeviceSynchronize());
86
+ CHECK(hipSetDevice(primary));
87
+
88
+ auto reduce_and_broadcast = [&]() {
89
+ if (p2p) {
90
+ CHECK(hipMemcpyPeerAsync(scratch, primary, peer_data, peer, bytes, stream));
91
+ } else {
92
+ CHECK(hipSetDevice(peer));
93
+ CHECK(hipMemcpy(host_stage, peer_data, bytes, hipMemcpyDeviceToHost));
94
+ CHECK(hipSetDevice(primary));
95
+ CHECK(hipMemcpy(scratch, host_stage, bytes, hipMemcpyHostToDevice));
96
+ }
97
+ LAUNCH_KERNEL(add_collective, blocks, 256, primary_data, scratch, count);
98
+ if (p2p) {
99
+ CHECK(hipMemcpyPeerAsync(peer_data, peer, primary_data, primary, bytes, stream));
100
+ CHECK(hipStreamSynchronize(stream));
101
+ } else {
102
+ CHECK(hipMemcpy(host_stage, primary_data, bytes, hipMemcpyDeviceToHost));
103
+ CHECK(hipSetDevice(peer));
104
+ CHECK(hipMemcpy(peer_data, host_stage, bytes, hipMemcpyHostToDevice));
105
+ CHECK(hipDeviceSynchronize());
106
+ CHECK(hipSetDevice(primary));
107
+ }
108
+ };
109
+
110
+ std::cout << "[PANTHEON] GPU " << primary << ": ALL_REDUCE with GPU " << peer
111
+ << (p2p ? " (peer DMA)" : " (host-staged fallback)") << std::endl;
112
+ auto start = std::chrono::high_resolution_clock::now();
113
+ // Time only the collective itself: the between-iteration re-initialization
114
+ // is bookkeeping, not interconnect traffic, and must not dilute GB/s.
115
+ double reduce_seconds = 0.0;
116
+ size_t transferred = 0;
117
+ do {
118
+ auto step_start = std::chrono::high_resolution_clock::now();
119
+ reduce_and_broadcast();
120
+ reduce_seconds += std::chrono::duration<double>(
121
+ std::chrono::high_resolution_clock::now() - step_start).count();
122
+ LAUNCH_KERNEL(init_collective, blocks, 256, primary_data, count, 1u);
123
+ CHECK(hipSetDevice(peer));
124
+ LAUNCH_KERNEL(init_collective, blocks, 256, peer_data, count, 2u);
125
+ CHECK(hipDeviceSynchronize());
126
+ CHECK(hipSetDevice(primary));
127
+ // One gather crossing plus one broadcast crossing per collective.
128
+ transferred += bytes * 2;
129
+ } while (std::chrono::duration_cast<std::chrono::seconds>(std::chrono::high_resolution_clock::now() - start).count() < duration);
130
+ double seconds = reduce_seconds > 0.0 ? reduce_seconds : 1e-6;
131
+ std::cout << "Throughput: " << (transferred / 1e9) / seconds << " GB/s" << std::endl;
132
+
133
+ int exit_code = 0;
134
+ if (verify) {
135
+ reduce_and_broadcast();
136
+ if (inject_error) {
137
+ CHECK(hipSetDevice(peer));
138
+ LAUNCH_KERNEL(corrupt_collective, 1, 1, peer_data);
139
+ CHECK(hipDeviceSynchronize());
140
+ }
141
+
142
+ unsigned int* primary_errors = nullptr;
143
+ unsigned int* peer_errors = nullptr;
144
+ unsigned int primary_error_count = 0;
145
+ unsigned int peer_error_count = 0;
146
+ CHECK(hipSetDevice(primary));
147
+ CHECK(hipMalloc(&primary_errors, sizeof(unsigned int)));
148
+ CHECK(hipMemset(primary_errors, 0, sizeof(unsigned int)));
149
+ LAUNCH_KERNEL(verify_collective, blocks, 256, primary_data, count, 3u, primary_errors);
150
+ CHECK(hipDeviceSynchronize());
151
+ CHECK(hipMemcpy(&primary_error_count, primary_errors, sizeof(primary_error_count), hipMemcpyDeviceToHost));
152
+ CHECK(hipFree(primary_errors));
153
+
154
+ CHECK(hipSetDevice(peer));
155
+ CHECK(hipMalloc(&peer_errors, sizeof(unsigned int)));
156
+ CHECK(hipMemset(peer_errors, 0, sizeof(unsigned int)));
157
+ LAUNCH_KERNEL(verify_collective, blocks, 256, peer_data, count, 3u, peer_errors);
158
+ CHECK(hipDeviceSynchronize());
159
+ CHECK(hipMemcpy(&peer_error_count, peer_errors, sizeof(peer_error_count), hipMemcpyDeviceToHost));
160
+ CHECK(hipFree(peer_errors));
161
+ unsigned int errors = primary_error_count + peer_error_count;
162
+ if (errors) {
163
+ std::cout << "Verification: FAIL (" << errors << " errors)" << std::endl;
164
+ exit_code = 1;
165
+ } else {
166
+ std::cout << "Verification: PASS" << std::endl;
167
+ }
168
+ }
169
+
170
+ CHECK(hipSetDevice(primary));
171
+ CHECK(hipStreamDestroy(stream));
172
+ CHECK(hipFree(primary_data));
173
+ CHECK(hipFree(scratch));
174
+ if (host_stage) CHECK(hipHostFree(host_stage));
175
+ CHECK(hipSetDevice(peer));
176
+ CHECK(hipFree(peer_data));
177
+ return exit_code;
178
+ }
@@ -0,0 +1,3 @@
1
+ # Allocation Fragmentation
2
+
3
+ Synthetic runtime working-set diagnostic. Run `pantheon --test allocation_fragmentation --duration 60 --gpu 0 --mem 25 --verify --profile`.
@@ -0,0 +1,177 @@
1
+ // Allocation Fragmentation
2
+ //
3
+ // This workload previously included the shared AI kernel template and performed
4
+ // no allocation at all -- it ran the same FMA loop as five other workloads while
5
+ // its name promised allocator behaviour. It now does what it says: repeatedly
6
+ // allocates and frees device memory in a pattern that fragments the heap, and
7
+ // measures how the allocator copes.
8
+ //
9
+ // The stress is on the driver's allocator, not on the GPU pipelines, so the
10
+ // device stays almost idle here by design.
11
+
12
+ #include "../common/common.h"
13
+
14
+ #include <algorithm>
15
+ #include <chrono>
16
+ #include <cstdio>
17
+ #include <cstdlib>
18
+ #include <iostream>
19
+ #include <string>
20
+ #include <vector>
21
+
22
+ // Touch each block so the allocation is actually backed, and so a handed-back
23
+ // pointer that overlaps a live one shows up as corruption rather than passing
24
+ // silently.
25
+ __global__ void stamp_block(unsigned int* block, size_t words, unsigned int tag) {
26
+ size_t stride = blockDim.x * gridDim.x;
27
+ for (size_t i = blockIdx.x * blockDim.x + threadIdx.x; i < words; i += stride) {
28
+ block[i] = tag ^ static_cast<unsigned int>(i);
29
+ }
30
+ }
31
+
32
+ __global__ void check_block(const unsigned int* block, size_t words, unsigned int tag,
33
+ unsigned int* errors) {
34
+ size_t stride = blockDim.x * gridDim.x;
35
+ for (size_t i = blockIdx.x * blockDim.x + threadIdx.x; i < words; i += stride) {
36
+ if (block[i] != (tag ^ static_cast<unsigned int>(i))) atomicAdd(errors, 1u);
37
+ }
38
+ }
39
+
40
+ int main(int argc, char* argv[]) {
41
+ if (argc < 4) return 1;
42
+ int gpu_id = atoi(argv[1]);
43
+ int duration = atoi(argv[2]);
44
+ int mem_pct = atoi(argv[3]);
45
+
46
+ bool verify_mode = false;
47
+ int inject_error = 0;
48
+ int block_size = 256, grid_size = 0, kernel_loops = 1, warmup_iters = 0, sync_mode = 2;
49
+ for (int i = 4; i < argc; ++i) {
50
+ std::string a(argv[i]);
51
+ if (a == "--verify") verify_mode = true;
52
+ else if (a == "--inject_error") inject_error = 1;
53
+ else if (a == "--block_size" && i + 1 < argc) block_size = atoi(argv[++i]);
54
+ else if (a == "--grid_size" && i + 1 < argc) grid_size = atoi(argv[++i]);
55
+ else if (a == "--warmup_iters" && i + 1 < argc) warmup_iters = atoi(argv[++i]);
56
+ else if (a == "--sync_mode" && i + 1 < argc) sync_mode = atoi(argv[++i]);
57
+ }
58
+ normalize_kernel_launch_config(block_size, grid_size, kernel_loops, warmup_iters, sync_mode);
59
+
60
+ CHECK(hipSetDevice(gpu_id));
61
+ hipDeviceProp_t prop;
62
+ CHECK(hipGetDeviceProperties(&prop, gpu_id));
63
+
64
+ size_t free_bytes = 0, total_bytes = 0;
65
+ CHECK(hipMemGetInfo(&free_bytes, &total_bytes));
66
+ mem_pct = mem_pct < 1 ? 1 : (mem_pct > 99 ? 99 : mem_pct);
67
+ size_t budget = (free_bytes * static_cast<size_t>(mem_pct)) / 100;
68
+
69
+ // A spread of sizes is what fragments a heap. Equal-sized blocks are always
70
+ // reusable and would never expose the behaviour this test is named for.
71
+ const size_t kSmall = 64u * 1024u;
72
+ const size_t kLarge = 8u * 1024u * 1024u;
73
+ const size_t kSlots = 512;
74
+
75
+ std::cout << "[PANTHEON] GPU " << gpu_id << ": Allocation Fragmentation" << std::endl;
76
+ std::cout << " -> Budget: " << (budget / (1024 * 1024)) << " MiB" << std::endl;
77
+ std::cout << " -> Block sizes: " << (kSmall / 1024) << " KiB to "
78
+ << (kLarge / (1024 * 1024)) << " MiB" << std::endl;
79
+ std::cout << " -> Slots: " << kSlots << std::endl;
80
+ std::cout << " -> Verify Mode: " << (verify_mode ? "ON" : "OFF") << std::endl;
81
+ if (inject_error) std::cout << "[PANTHEON] Warning: SDC Fault Injection is ACTIVE!" << std::endl;
82
+
83
+ std::vector<unsigned int*> slots(kSlots, nullptr);
84
+ std::vector<size_t> sizes(kSlots, 0);
85
+ std::vector<unsigned int> tags(kSlots, 0);
86
+ size_t live_bytes = 0;
87
+ unsigned long long allocations = 0, frees = 0, failures = 0;
88
+ unsigned int* d_errors = nullptr;
89
+ if (verify_mode) {
90
+ CHECK(hipMalloc(&d_errors, sizeof(unsigned int)));
91
+ CHECK(hipMemset(d_errors, 0, sizeof(unsigned int)));
92
+ }
93
+
94
+ unsigned int rng = 0x9E3779B9u;
95
+ auto next = [&rng]() { rng ^= rng << 13; rng ^= rng >> 17; rng ^= rng << 5; return rng; };
96
+
97
+ std::cout << "[PANTHEON] Starting active telemetry phase..." << std::endl;
98
+ auto start = std::chrono::high_resolution_clock::now();
99
+ do {
100
+ for (size_t round = 0; round < kSlots; ++round) {
101
+ size_t slot = next() % kSlots;
102
+
103
+ if (slots[slot]) {
104
+ // Free roughly half the live blocks each pass, leaving holes of
105
+ // mixed sizes behind rather than a clean sweep.
106
+ CHECK(hipFree(slots[slot]));
107
+ live_bytes -= sizes[slot];
108
+ slots[slot] = nullptr;
109
+ sizes[slot] = 0;
110
+ ++frees;
111
+ continue;
112
+ }
113
+
114
+ size_t want = kSmall + (static_cast<size_t>(next()) % (kLarge - kSmall));
115
+ want &= ~static_cast<size_t>(255);
116
+ if (live_bytes + want > budget) continue;
117
+
118
+ unsigned int* block = nullptr;
119
+ if (hipMalloc(&block, want) != hipSuccess || block == nullptr) {
120
+ // A refusal while well under budget is the fragmentation signal.
121
+ ++failures;
122
+ continue;
123
+ }
124
+ size_t words = want / sizeof(unsigned int);
125
+ unsigned int tag = next();
126
+ int grid = init_launch_grid_size(prop, words, block_size);
127
+ LAUNCH_KERNEL(stamp_block, grid, block_size, block, words, tag);
128
+ slots[slot] = block;
129
+ sizes[slot] = want;
130
+ tags[slot] = tag;
131
+ live_bytes += want;
132
+ ++allocations;
133
+ }
134
+ CHECK(hipDeviceSynchronize());
135
+ } while (std::chrono::duration_cast<std::chrono::seconds>(
136
+ std::chrono::high_resolution_clock::now() - start).count() < duration);
137
+
138
+ double seconds = std::chrono::duration<double>(
139
+ std::chrono::high_resolution_clock::now() - start).count();
140
+
141
+ std::cout << "Throughput: " << (static_cast<double>(allocations + frees) / seconds)
142
+ << " alloc-events/s" << std::endl;
143
+ std::cout << " -> Allocations: " << allocations << std::endl;
144
+ std::cout << " -> Frees: " << frees << std::endl;
145
+ std::cout << " -> Refusals: " << failures << " (allocator declined while under budget)" << std::endl;
146
+ std::cout << " -> Live at end: " << (live_bytes / (1024 * 1024)) << " MiB" << std::endl;
147
+
148
+ int exit_code = 0;
149
+ if (verify_mode) {
150
+ std::cout << "[PANTHEON] Verifying every live block still holds its tag..." << std::endl;
151
+ if (inject_error) {
152
+ for (size_t s = 0; s < kSlots; ++s) {
153
+ if (slots[s]) {
154
+ unsigned int bad = 0x0BADBEEFu;
155
+ CHECK(hipMemcpy(slots[s], &bad, sizeof(bad), hipMemcpyHostToDevice));
156
+ break;
157
+ }
158
+ }
159
+ }
160
+ for (size_t s = 0; s < kSlots; ++s) {
161
+ if (!slots[s]) continue;
162
+ size_t words = sizes[s] / sizeof(unsigned int);
163
+ int grid = init_launch_grid_size(prop, words, block_size);
164
+ LAUNCH_KERNEL(check_block, grid, block_size, slots[s], words, tags[s], d_errors);
165
+ }
166
+ CHECK(hipDeviceSynchronize());
167
+ unsigned int host_errors = 0;
168
+ CHECK(hipMemcpy(&host_errors, d_errors, sizeof(unsigned int), hipMemcpyDeviceToHost));
169
+ std::cout << "Verification: " << (host_errors ? "FAIL" : "PASS")
170
+ << " (" << host_errors << " corrupted words across live blocks)" << std::endl;
171
+ exit_code = host_errors ? 1 : 0;
172
+ }
173
+
174
+ for (size_t s = 0; s < kSlots; ++s) if (slots[s]) CHECK(hipFree(slots[s]));
175
+ if (d_errors) CHECK(hipFree(d_errors));
176
+ return exit_code;
177
+ }
@@ -0,0 +1,57 @@
1
+ # Atomic Virus
2
+
3
+ `atomic_virus` is an L2/cache-arbiter stress test. It repeatedly performs atomic adds across a large VRAM allocation, forcing read-modify-write traffic that is harder on cache arbitration and memory ordering than plain reads or writes.
4
+
5
+ ![Atomic Virus execution flow](./atomic_virus_flow.svg)
6
+
7
+ ## What It Stresses
8
+
9
+ | Area | Stress mechanism |
10
+ | :--- | :--- |
11
+ | L2 cache arbiters | Many threads contend on atomic read-modify-write paths. |
12
+ | Memory fabric | Wide grid-stride access walks a large allocation. |
13
+ | Ordering hardware | Atomic operations force serialization at cache-line granularity. |
14
+ | Retention/correctness | Optional verification checks the expected atomic count. |
15
+
16
+ ## How It Works
17
+
18
+ 1. The test uses `--mem` percent of available VRAM to size the buffer, but **the implementation clamps the allocation** (currently 128 MiB max) so each kernel launch finishes in bounded time. On very large GPUs, `--mem 99` would otherwise imply trillions of atomics **per launch** before the next `hipDeviceSynchronize`, and the host watchdog (`duration + 30` s in `pantheon.py`) would SIGKILL the process with exit code **-9** while telemetry still shows `0.0 ERR`. For a true “almost full VRAM” allocation check, use a different test; keep `atomic_virus` for L2/atomic stress at the clamped footprint.
19
+ 2. Memory is initialized to zeroes or ones.
20
+ 3. Each thread walks the allocation as `uint4` storage reinterpreted as `unsigned int`.
21
+ 4. For each visited integer, the kernel performs `kernel_loops` atomic adds.
22
+ 5. Warmup updates are reset before the measured phase so verification has a clean baseline.
23
+ 6. With `--verify`, the final values are compared against the expected launch count.
24
+
25
+ ## Command Examples
26
+
27
+ ```bash
28
+ pantheon --test atomic_virus --gpu 0 --duration 30 --mem 60
29
+ pantheon --test atomic_virus --gpu 0 --duration 30 --mem 60 --verify
30
+ ```
31
+
32
+ ## Runtime Parameters
33
+
34
+ | Parameter | Default | Effect |
35
+ | :--- | ---: | :--- |
36
+ | `block_size` | `256` | Threads per block. |
37
+ | `grid_size` | `0` | Number of blocks. `0` means auto-calculate from occupancy. |
38
+ | `kernel_loops` | `100` | Atomic adds per visited integer. |
39
+ | `warmup_iters` | `5` | Warmup launches before telemetry, followed by a memory reset. |
40
+ | `sync_mode` | `2` | `0=Spin`, `1=Yield`, `2=Block`. |
41
+ | `init_pattern` | `0` | `0=Zeroes`, `1=Ones`. |
42
+
43
+ ## Output And Interpretation
44
+
45
+ `Throughput` is reported in `MAPS`: million atomic operations per second. Higher MAPS means more atomic traffic, but the most stressful configuration may be the one that produces higher power, temperature, or throttle signals rather than raw throughput.
46
+
47
+ ## Failure Signals
48
+
49
+ | Symptom | Possible meaning |
50
+ | :--- | :--- |
51
+ | Verification mismatch | Atomic count mismatch, cache/L2 fault, or injected corruption. |
52
+ | Very low MAPS | Severe atomic serialization, throttling, or too much memory footprint. |
53
+ | High power with modest MAPS | Useful stress point: the fabric is busy even when progress is slow. |
54
+
55
+ ## Source
56
+
57
+ The implementation lives in [`atomic_virus.cpp`](./atomic_virus.cpp).