Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/skills/gfxgraph-development/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,26 @@ print(f"Avg replay: {s['avg_replay_us']:.1f} µs")
- The monkey-patch itself (`enable`/`disable`): Thread-safe (one-time setup)
- HIP Graph capture: Must be done on the thread that owns the CUDA stream

### Process-global capture serialization (multi-session / "2 LLMs in one process")

On gfx1030/RDNA2, HIP stream-capture bookkeeping is **process-global** even with
`hipStreamCaptureModeThreadLocal`. Two sessions that capture graphs at the same time
corrupt each other's output (NaN) — a ROCm-runtime limitation, not a gfxGRAPH bug.

gfxGRAPH guards this with one process-wide reader/writer gate in Rust
(`rs_gfxgraph_core::capture_gate`, surfaced as `rs_gfxgraph.CaptureLock` / `ReplayLock`):

- **Capture → write lock (exclusive):** every capture site (`capture_begin`/`capture_end`,
the standard capture context, `ShapeBucketPool` lazy bucket capture, and each
`ConditionalGraph` branch) holds it, so only one capture runs at a time process-wide.
- **Replay → read lock (shared):** replays run fully concurrently; excluded only during the
brief one-time capture window.

Net effect: multi-session capture is automatically safe — both models capture (serialized)
and replay (parallel) with no caller action. The gate releases the GIL while blocking and
no-ops on pure-Python installs (native extension absent). This is distinct from, and
complementary to, the per-runner `ReentrancyGuard` in `ConditionalGraphRunner`.

## Version History

- **v0.3.4** — Current. Pure-Python base install (native bridge via the `native/` companion + source Rust crates), per-branch memory pools, accurate structural fallback metrics, RDNA2 DeepSpeed-HIP + Triton kernels, dynamic-shape and adaptive-replay fixes.
Expand Down
82 changes: 82 additions & 0 deletions .jules/reports/benchmark_2026-06-16.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
{
"timestamp_utc": "2026-06-16T13:30:46Z",
"commit_sha": "fe14ca8017e25f29248aa9bcefdb811cbc0c1e5e",
"run_count": 3,
"env": {
"torch": "2.13.0a0+git53bbebe",
"device": "AMD Radeon RX 6700 XT",
"rocm": {
"runtime_from_torch": "7.2.26015",
"driver_from_hipconfig": "7.2.26015-fc0010cf6a",
"runtime_from_rocminfo": "Runtime Version: 1.18"
},
"env": {
"HSA_OVERRIDE_GFX_VERSION": "10.3.0",
"PYTORCH_ROCM_ARCH": "gfx1030",
"GFXGRAPH": null,
"GFXGRAPH_VRAM_CAP": null,
"SGLANG_RDNA2_KERNELS": null,
"HIP_VISIBLE_DEVICES": null,
"CUDA_VISIBLE_DEVICES": null
}
},
"results": [
{
"workload": "decode_like_layernorm_gelu_chain_bs1_d1024",
"iters": 2000,
"run_count": 3,
"eager_ms_per_iter": 0.1454837964993203,
"graph_ms_per_iter": 0.18561912199947983,
"eager_ms_per_iter_runs": [
0.14926297799866006,
0.1454837964993203,
0.14496194149978692
],
"graph_ms_per_iter_runs": [
0.18561912199947983,
0.18482524499995634,
0.18814137000117626
],
"speedup_x": 0.7837759112971562,
"fallback": true
},
{
"workload": "mlp_bs32_d1024",
"iters": 1500,
"run_count": 3,
"eager_ms_per_iter": 0.10141401733320284,
"graph_ms_per_iter": 0.10106284666593031,
"eager_ms_per_iter_runs": [
0.09671573933398274,
0.10141401733320284,
0.10166068333152604
],
"graph_ms_per_iter_runs": [
0.10262902933512426,
0.10100084866765731,
0.10106284666593031
],
"speedup_x": 1.0034747751409907,
"fallback": true
},
{
"workload": "mlp_bs128_d2048",
"iters": 300,
"run_count": 3,
"eager_ms_per_iter": 0.6040697966697431,
"graph_ms_per_iter": 0.6013785733375698,
"eager_ms_per_iter_runs": [
0.6040697966697431,
0.6094511733317631,
0.6013353733336165
],
"graph_ms_per_iter_runs": [
0.6013785733375698,
0.6010160533332964,
0.6156069300050149
],
"speedup_x": 1.0044750901536736,
"fallback": true
}
]
}
10 changes: 10 additions & 0 deletions .jules/verification/rusty/after-benchmark.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"candidate": "python/hipgraph_bridge/conditional.py",
"implementation": "after",
"command": "python benchmarks/bench_conditional_mock.py",
"timestamp": "2026-05-08T00:00:00Z",
"iterations": 200000,
"input_description": "Alternating branch execution (mocked GPU)",
"duration_ms": 8096.94689099706,
"throughput": "24700.67 ops/sec"
}
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,39 @@

All notable changes to this project are documented in this file.

## [1.1.0] - 2026-06-21

### Fixed
- **Concurrent multi-session graph capture corruption on gfx1030/RDNA2**: when two
in-process LLM sessions captured CUDA/HIP graphs at the same time, output could come
back as NaN. Root cause is in the ROCm runtime, not gfxGRAPH: HIP stream-capture
bookkeeping is **process-global** even with `hipStreamCaptureModeThreadLocal`, so
concurrent captures clobber each other. gfxGRAPH now serializes capture process-wide
with a single Rust reader/writer gate (`rs_gfxgraph_core::capture_gate`, exposed as
`rs_gfxgraph.CaptureLock` / `ReplayLock`): **capture takes the write lock (one at a
time, excludes in-flight replay); replay takes the shared read lock (fully concurrent
across sessions).** Both LLMs still capture their graphs — just never simultaneously —
and replay stays parallel, so the high-level-capture value proposition is preserved.
The lock is acquired with the GIL released to avoid deadlock, and degrades to a no-op
when the native extension is absent (pure-Python install). Every capture site
(`capture_begin`/`capture_end`, the standard capture context, shape-bucket lazy capture,
and conditional-branch capture) is serialized; replay sites take the shared lock.

## [rust-hip-cpp] - 2026-06-16

### Added
- **Integrated Rust-C++-HIP Launcher & Interposer**:
- Programmatic `HSA_OVERRIDE_GFX_VERSION=10.3.0` auto-injection on library initialization for AMD RDNA2 devices (gfx1030/gfx1031).
- Dynamically resolved CPU Core Complex (CCX) / L3 cache thread affinity pinning on AMD Zen CPUs (Ryzen 9 3900X) to eliminate Infinity Fabric thread-switching latency.
- Zero-allocation, AVX2-friendly loop contiguity verification and multidimensional offset computation inside `rs_gfxgraph_core` layout modules.
- Thread-safe RAII re-entrancy prevention guard (`ReentrancyGuard`) in `ConditionalGraphRunner` wrapper to cleanly route overlapping streams to safe eager fallbacks.
- Multi-symbol C++ CUDA compatibility interposer (`cuda_intercept.c`) with a native update-and-launch pipeline shortcut bypassing Python overhead.
- **Benchmarking & Testing Hardening**:
- Added new native C++/HIP test executable `test_routing.hip` to verify shape bucket selection and bounds checks directly on the GPU.
- Created `gfxgraph-benchmarking` skill to guide profiling, public benchmarking (`bench_readme_public.py`), and micro-benchmarking on ROCm.
- Authored a comprehensive `benchmarking-guide.md` covering the micro-benchmark suites, public GPU benchmark config, and provenance JSON schema.
- Patched `bench_routing.py` and `bench_conditional_mock.py` to support graceful mock-execution fallbacks on CPU/system environments.

## [1.0.1] - 2026-06-16

### Fixed
Expand Down
23 changes: 21 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.21)
project(gfxGRAPH
VERSION 0.3.4
DESCRIPTION "CUDA Graph → HIP Graph translation layer for gfx1030 RDNA2"
LANGUAGES CXX HIP
LANGUAGES C CXX HIP
)

include(CheckIPOSupported)
Expand All @@ -17,9 +17,12 @@ find_package(hip REQUIRED)
# ── Layer 1: Core bridge library ───────────────────────
add_library(hipgraph_bridge SHARED
src/init.cpp
src/profiler.cpp
src/runtime_handles.cpp
src/conditional_bridge.hip
src/launch_pipeline.hip
src/shape_manager.hip
src/decode_pool.hip
src/capture_compositor.hip
src/graph_utils.hip
)
Expand Down Expand Up @@ -65,8 +68,16 @@ if(BUILD_CUDA_COMPAT)
)
target_link_libraries(cudagraph_compat PRIVATE
hipgraph_bridge
hip::amdhip64
${CMAKE_DL_LIBS}
)
target_include_directories(cudagraph_compat PRIVATE
/opt/rocm/include
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
)
target_compile_definitions(cudagraph_compat PRIVATE
__HIP_PLATFORM_AMD__=1
)
set_target_properties(cudagraph_compat PROPERTIES
OUTPUT_NAME cudagraph_compat
)
Expand All @@ -77,12 +88,20 @@ option(BUILD_TESTS "Build test executables" ON)
if(BUILD_TESTS)
enable_testing()

foreach(gap IN ITEMS conditional pipeline shapes compositor)
foreach(gap IN ITEMS conditional pipeline shapes compositor routing decode)
add_executable(test_${gap} tests/test_${gap}.hip)
target_link_libraries(test_${gap} PRIVATE hipgraph_bridge)
add_test(NAME ${gap} COMMAND test_${gap})
endforeach()

add_executable(test_profiler tests/test_profiler.hip)
target_link_libraries(test_profiler PRIVATE hipgraph_bridge)
add_test(NAME profiler COMMAND test_profiler)

add_executable(test_runtime_handles tests/test_runtime_handles.hip)
target_link_libraries(test_runtime_handles PRIVATE hipgraph_bridge)
add_test(NAME runtime_handles COMMAND test_runtime_handles)

if(BUILD_CUDA_COMPAT)
add_test(
NAME compat_smoke
Expand Down
Loading
Loading