You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
4.16.0: device-local new T[N>32] dynamic-index correct on all 6 backends (Wasm fix) + CUDA graph API rollup
LowerArrays: a per-thread device-local `var acc = new T[N]` (N>32) written+read by a
runtime index read back 0 on Wasm (correct on the other 5 backends). The rewriter
positions new values at value.Index+1, so the alloca/view/defaultElement created while
lowering NewArray landed AFTER `value`; SplitBlock(value) then pushed that setup into the
loop EXIT block, leaving the array view DEFINED in the exit while the zero-init loop body
USES it - an SSA dominance violation. GPU backends rematerialize the static alloca address
at each use and tolerated it; the Wasm state machine ran the zero-init loop with an unset
(0) view local and clobbered low linear memory.
Fix: create the setup BEFORE `value` (builder.SetupInsertPosition(value)) so it stays in
the dominating current block while SplitBlock(value) exports only the user code.
Result-neutral for the 5 GPU backends; unroll path (N<=32) byte-identical. (A first attempt
that split at defaultElement orphaned that constant - SplitBlock removes its split point -
and regressed the PTX/OpenCL fixpoint analysis; caught by the full PMT sweep.)
Un-skips BackendTestBase.LocalArray_DynamicIndex_MatchesCpuOracle on Wasm.
Full PMT sweep: 4006 passed / 0 failed / 260 skipped.
Stable cut 4.16.0 / forks 2.1.0 (minor - new public CUDA graph API lives in the fork):
rolls up CUDA graph capture API + Accelerator.WithDefaultStream + ShaderDebugService.AppLoadTimestamp.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+19Lines changed: 19 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,6 +2,25 @@
2
2
3
3
This file tracks notable changes per release. The README's "Recent Highlights" section links here for the full version history.
4
4
5
+
## 4.16.0 (2026-06-23) - CUDA graph capture API + device-local dynamic-index array fix complete on all 6 backends
6
+
7
+
Stable cut over 4.15.1. Forks bump to **2.1.0** (minor, not patch: this release adds genuinely new public API in the fork - see the fork-version note at the bottom of this entry). Rolls up the 4.15.2-local and 4.15.3-local builds plus the final Wasm fix. Two headline items:
8
+
9
+
**1. CUDA graph capture/replay API** (new public surface in `ILGPU.Runtime.Cuda`). Capture a fixed-shape kernel sequence once and replay it with a single `cuGraphLaunch`, collapsing per-kernel host dispatch overhead (built for LLM decode in SpawnDev.ILGPU.ML).
10
+
-`CudaStream.BeginCapture(CudaStreamCaptureMode = ThreadLocal)` / `.EndCapture()` -> `CudaGraph` / `.CaptureStatus` / `CudaStream.SupportsGraphCapture`. `BeginCapture` throws on the default (NULL) stream - use a dedicated `accelerator.CreateStream()`.
11
+
-`CudaGraph.Instantiate()` -> `CudaGraphExec.Launch(stream)` / `.Upload(stream)`. Both are context-bound `AcceleratorObject`s.
12
+
-`Accelerator.WithDefaultStream(stream)` (all backends) - a scoped swap (restores on dispose) that reroutes every implicitly-grouped `*StreamKernel` launch onto one capturable stream with no per-call-site change.
13
+
- Native graph entry points bound by hand against the loaded driver (same approach as `NvvmAPI`), cross-platform. Verified on RTX 4070 (`DemoConsole -- cuda-graph-capture`): capture inert, replay bit-exact vs CPU reference, ~6.6-7x dispatch microbench.
14
+
15
+
**2. Device-local dynamically-indexed `new T[]` arrays now correct on ALL 6 backends.** A per-thread device-LOCAL array `var acc = new float[N];` (compile-time size, **N > 32**) that is WRITTEN and READ by a **runtime index** is now correct on CUDA, OpenCL, CPU, WebGPU, WebGL, and Wasm. Two stacked `ILGPU/IR/Transformations/LowerArrays.cs` fixes:
16
+
-**(a) Register-allocation crash (N > 32 init loop), from 4.15.3-local.1:** for N > 32 the array zero-init is an IR loop; its counter phi took its initial `0` from the loop **header** instead of the **predecessor**, breaking SSA dominance ("No register allocated for PrimitiveValue 0" at JIT). Only surfaced with dynamic indexing (static indices scalar-replace the array) and N > 32 (N <= 32 unrolls). Fix: create the init `0` in the predecessor.
17
+
-**(b) Wasm "reads 0", new in this release:** fix (a) unmasked a Wasm-only miscompile. The rewriter positions new values at `value.Index + 1`, so the alloca/view/defaultElement created while lowering `NewArray` landed AFTER `value`; `SplitBlock(value)` then pushed that setup into the loop EXIT block, leaving the array view DEFINED in the exit while the zero-init loop body USES it - an SSA dominance violation. GPU backends rematerialize the static alloca address at each use and tolerated it; the Wasm state machine executes the literal block order, so the zero-init loop ran with an unset (0) view local and clobbered low linear memory (read back 0). Fix: create the setup BEFORE `value` (`builder.SetupInsertPosition(value)`) so it stays in the dominating current block while `SplitBlock(value)` exports only the user code. Result-neutral for the 5 GPU backends; the unroll path (N <= 32) is byte-identical.
18
+
- Gate: `BackendTestBase.LocalArray_DynamicIndex_MatchesCpuOracle` (N=64, runtime index in a loop, CPU oracle) - passes on all 6 backends; the previous Wasm named-skip is removed. Full PMT sweep **4006 passed / 0 failed / 260 skipped (4266 total)**.
19
+
20
+
Also includes `ShaderDebugService.AppLoadTimestamp` (4.15.2-local.2).
21
+
22
+
**Fork version note:** the `SpawnDev.ILGPU.Fork` / `.Algorithms.Fork``2.x` line is normally a lockstep sync counter bumped by patch. This release moves it to a **minor** (`2.0.x` -> `2.1.0`) because the CUDA graph API is genuinely new public surface that lives in the fork (`ILGPU/`), not the wrapper. Going forward: minor-bump the fork only when `ILGPU/` gains real public API, patch for bugfix/sync-only bundles.
Forks bump to `2.0.44-local.1`. A per-thread device-LOCAL array `var acc = new float[N];` (compile-time size, **N > 32**) that is WRITTEN and READ by a **runtime index inside a loop** threw `InvalidCodeGenerationException` ("No register allocated for PrimitiveValue 0") at kernel JIT - blocking the register/local-memory-accumulator universal (flash-class) per-query attention kernel (SpawnDev.ILGPU.ML, Tuvok).
Copy file name to clipboardExpand all lines: CLAUDE.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -45,7 +45,7 @@ Detailed constraints live in each directory's own `CLAUDE.md`. Read the relevant
45
45
46
46
Tests in `SpawnDev.ILGPU.Demo.Shared/UnitTests/BackendTestBase*.cs` (~211 tests, Tests1-10). Backend-specific classes inherit and override unsupported tests. See `PlaywrightMultiTest/CLAUDE.md` for running tests.
47
47
48
-
**Current version: see [CHANGELOG.md](CHANGELOG.md) — it is the SINGLE SOURCE OF TRUTH for versions/features (this header is NOT kept in lockstep; do not trust a version number written below).** As of 2026-06-22: nuget.org stable = **4.15.1** (forks `2.0.42`); local feed (`D:\users\SpawnDevPackages`) latest = **4.15.3-local.1** (forks `2.0.44-local.1`) = CUDA graph capture API (`CudaStream.BeginCapture/EndCapture` + `CudaGraph`/`CudaGraphExec` + `Accelerator.WithDefaultStream`) + the device-local dynamically-indexed `new T[]` codegen fix (works on CUDA/OpenCL/CPU/WebGPU/WebGL; ⚠ Wasm N>32 dynamic-index still reads 0 — use `LocalMemory.Allocate<T>(N)`, see `Wasm/CLAUDE.md`). The rest of this paragraph is HISTORICAL context (rc.7–rc.10 era):
48
+
**Current version: see [CHANGELOG.md](CHANGELOG.md) — it is the SINGLE SOURCE OF TRUTH for versions/features (this header is NOT kept in lockstep; do not trust a version number written below).** As of 2026-06-23: nuget.org stable target = **4.16.0** (forks `2.1.0`) = CUDA graph capture API (`CudaStream.BeginCapture/EndCapture` + `CudaGraph`/`CudaGraphExec` + `Accelerator.WithDefaultStream`) + the device-local dynamically-indexed `new T[N>32]` codegen fix now correct on **all 6 backends incl Wasm** (`LowerArrays` view-def-block placement; full PMT 4006/0/260). Previous stable = 4.15.1 (forks 2.0.42). The rest of this paragraph is HISTORICAL context (rc.7–rc.10 era):
49
49
50
50
**rc.10 headline**: LocalMemory<T>(N>=32) WGSL codegen 5-layer fix (unblocks Tuvok's Vp9Idct8x8Kernel + 16x16/32x32/iADST/iHT kernel family on WebGPU bit-exact), `AcceleratorRequirements` capability-gating API + extension methods, `UnsupportedKernelFeatureException` typed exception wired at WebGL GenericAtomic + AtomicCAS codegen sites. Regression test `LocalMemoryRepro_Int64_ShortByteViews` locks down both the WebGPU fix and the WebGL architectural varying-count ceiling. rc.10 docs landed in README "What's New in 4.9.2." **Current P2P sibling: 4.9.2-rc.22** (WebTorrent 3.1.4, full 6-gap audit closed, binary wire framing for BufferSend/BufferData via `P2PBinaryFrame` + ConfigureHighThroughputSctp helper - 10MB WebRTC dispatch passes in 25s). **Pending at HEAD (historical context, shipped in rc.7+): f16 emulation Phases 1 + 2 + 3** - `Capabilities.Float16` always true across WebGPU / WebGL / Wasm / OpenCL; `Capabilities.Float16Native` distinguishes native-vs-emulated on backends where both paths exist (WebGPU, OpenCL); `WebGPUBackend.ForceEmulatedF16` test flag. Emulation paths: WebGPU WGSL `_f16_to_f32` / `_f32_to_f16` helpers + packed u16 storage; WebGL GLSL helpers + Transform Feedback uint output; OpenCL `vload_half` / `vstore_half` built-ins (no extension required) + f32 arithmetic. Full `hardwareConcurrency` multi-worker barrier dispatch with pure-spin generation barriers (wait/notify races on V8 — see Wasm/CLAUDE.md "Barriers are PURE SPIN") and in-Wasm phase dispatcher (no JS-Wasm boundary crossings between phases). All large sort tests (260K-4M) passing including SpawnSceneSimulation (1.4M elements, multi-frame). rc.7 key fixes: WGSL spinlock-key refactor (tuple-keyed `array<atomic<u32>>` for f64 Min/Max/Exchange), Wasm cascade-safe Dispose (per-worker TCS fault on dispose), wait/notify barrier with wakeup loop (replaced pure spin after diagnosing spurious wakeup bug - not a V8 bug), shared memory alloca overlap (same-size dedup), IR address space aliasing (InferAddressSpaces guards), struct/scratch overlap, multi-pass scan, Float16, unsigned ops, 256 threads, memory.grow(), ViewSourceSequencer, subViewByteOffset, atomic RMW opcode table, CopyFromBuffer, onesComplementMask .tt template, per-worker scratch, atomic.fence at 3 sync points, float atomic stores, broadcast atomic store/load, barrier counter zeroing between groups.
Copy file name to clipboardExpand all lines: SpawnDev.ILGPU/SpawnDev.ILGPU.csproj
+3-3Lines changed: 3 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@
4
4
<TargetFramework>net10.0</TargetFramework>
5
5
<ImplicitUsings>enable</ImplicitUsings>
6
6
<Nullable>enable</Nullable>
7
-
<Version>4.15.3-local.1</Version>
7
+
<Version>4.16.0</Version>
8
8
<!-- Brief current-version highlights only. Full per-version history with code samples lives in CHANGELOG.md (linked from the README). -->
9
9
<PackageReleaseNotes>4.15.3-local.1: Device-LOCAL dynamically-indexed array codegen fix (Fork 2.0.44-local.1). A per-thread `new T[N]` (N>32) written/read by a RUNTIME index in a loop threw InvalidCodeGenerationException ("No register allocated for PrimitiveValue 0") at kernel JIT. Root cause: the LowerArrays N>32 zero-init loop created the counter-phi's initial 0 constant in the loop HEADER instead of the predecessor block (invalid SSA dominance). Fixed (result-neutral). Verified compile+correct on CUDA/OpenCL/CPU/WebGPU/WebGPU-no-subgroups/WebGL; one tracked Wasm-only follow-up (large dynamically-indexed local alloca with scratchOffset!=0). Unblocks register/local-memory accumulator kernels (flash-class per-query attention) on the GPU backends. Also includes 4.15.2-local CUDA graph capture API + Accelerator.WithDefaultStream + ShaderDebugService.AppLoadTimestamp.
0 commit comments