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
FP4 (Float4E2M1) browser backends (WGSL/GLSL/Wasm) + host scalar-param fix - FP4 now on ALL 6 backends - 4.14.0-local.5
Completes Float4E2M1 (OCP E2M1FN, the NVFP4/MXFP4 element format) across every backend. The
convert/decode is now BIT-EXACT to ml_dtypes.float4_e2m1fn on CPU, CUDA, OpenCL, WebGPU, WebGL,
and Wasm. Four-package bundle: forks 2.0.31 -> 2.0.32, SpawnDev.ILGPU 4.14.0-local.4 -> local.5.
Browser convert codegen (mirrors the FP8 WGSL/GLSL/Wasm paths; the _e2m1<->f32 helpers are
line-for-line ports of the CPU/OpenCL/CUDA-verified managed conversion, byte-identical across all 6):
- WebGPU/WGSL: _e2m1_to_f32 / _f32_to_e2m1 in WGSLEmulationLibrary (minimal-trim gated) + type map
(f32) + FloatAsInt/IntAsFloat + const + every sub-word classification/scalar/load/store/LEA site.
- WebGL/GLSL: _e2m1_to_f32 / _f32_to_e2m1 in GLSLEmulationLibrary + type map + FloatAsInt/IntAsFloat
+ const + body-struct/param/load(texelFetch)/store(TF) sites.
- Wasm: EmitFP4ToF32 / EmitF32ToFP4 inline bytecode + load (i32.load8_u) / store (i32.store8) /
const + the struct-wrapper mis-lowering store guard.
Host sub-word SCALAR-param fix (Rule 2a - this was a latent FP8 gap too; FP8 only had buffer
round-trip tests, never a scalar-param test):
- A by-value 1-byte float scalar (scale/bias in the generic relu kernel) fell through the host
scalar marshaling with no FP8/FP4 case: Wasm struct-serialized it (kernel read garbage -> "got 2"),
WebGL never sent the uniform (arrived as 0). Added FP8 (E4M3/E5M2) + FP4 to the host widen-to-f32
path next to Half/bf16 in WasmAccelerator + WebGLAccelerator (the f32-register model; the scalar
param is declared f32/float on these backends, so pass the widened value, lossless).
Capability + tests:
- AcceleratorRequirements.RequiresFloat4E2M1 + HasFloat4() (always-true no-op filter like bf16/FP8).
- PMT BackendTestBase.GenericPrecision: PrecisionConvert_Float4E2M1_RoundTripBitExact,
GenericPrecision_Float4E2M1_RunsAndMatchesCpu (FP4-exact scale=1.5/bias=0.5 scalar params),
Float4E2M1_FloatToFP4_RneSaturateNaN (decode/overflow/NaN bit-exact vs managed).
- AcceleratorRequirementsTests.Satisfies_LowPrecisionFloats extended with FP4.
Gates: PMT Float4E2M1 23/0 ALL 6 backends; GenericPrecision (Half/bf16/FP4 scalar relu) 30/0;
AcceleratorRequirements 19/0/1; no regression (PrecisionConvert_Float8 16/0, desktop fp8-verify
257/257 + fp4-verify CPU/OpenCL/CUDA bit-exact, bf16-f16-oracle 65536/65536). NEXT (separate
commit): FP4 radix-sort keys, then INT4, then MXFP4/NF4 dequant.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+9Lines changed: 9 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,6 +2,15 @@
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.14.0-local.5 (2026-06-17) - New 4-bit float type `Float4E2M1` (NVFP4/MXFP4 element format) on all 6 backends + a latent low-precision store-widening bug fix
6
+
7
+
Adds `ILGPU.Float4E2M1`, the OCP **E2M1FN** 4-bit float (the element format of NVFP4 / MXFP4): 1 sign / 2 exp / 1 mantissa, bias 1, **16 finite codes (no Inf, no NaN)**, magnitudes `{0,.5,1,1.5,2,3,4,6}`, max 6, finite overflow + ±Inf saturate to ±6, NaN→-0. 1-byte storage (value in the low nibble), f32-register compute. Forks bump to `2.0.32`. Bit-exact to `ml_dtypes.float4_e2m1fn` (PyTorch/JAX share it).
8
+
9
+
-**First-class IR primitive on all 6 backends** (CPU, CUDA, OpenCL, WebGPU, WebGL, Wasm), mirroring the FP8 wiring: `BasicValueType.Float4E2M1` + `ArithmeticBasicValueType.Float4E2M1` (appended at the end - all existing ordinals + positional type tables unchanged), `INumber<Float4E2M1>` (E2M1 has neither Inf nor NaN), const-fold, `Interop.FloatAsInt`, and `AcceleratorRequirements.RequiresFloat4E2M1` (always-true no-op filter like bf16/FP8). The float↔FP4 conversion is **portable bit-manipulation** on every backend (no native cvt → works on every CUDA arch incl. pre-Ampere 1080/2060), byte-identical across all 6.
10
+
-**Fixed a real latent low-precision store bug (Rule 2a).** On PTX the "low-precision value stored to a wider buffer" guard (`floatBuf[i] = (float)lowpBuf[i]`) covered only bf16, so an FP8 **or** FP4 decode-to-float emitted `st.b8` into the 4-byte slot → read back ~0. Found via the FP4 decode kernel + a PTX dump; generalized the guard to bf16 + Float8E4M3 + Float8E5M2 + Float4E2M1. FP8 decode-to-float was silently broken (untested) before this.
11
+
-**Fixed FP8/FP4 by-value sub-word SCALAR params on Wasm + WebGL.** A by-value 1-byte float scalar (e.g. `scale`/`bias` in a generic relu kernel) fell through the host scalar-marshaling switch (no FP8/FP4 case) → struct-serialized (Wasm: garbage) / uniform never sent (WebGL: arrived as 0). Added FP8 + FP4 to the host widen-to-f32 path next to Half/bf16 (the f32-register model). This was a latent FP8 gap too - FP8 only had buffer round-trip tests, never a scalar-param test.
12
+
- Gates: PMT `Float4E2M1` (round-trip + generic relu with FP4 scalar params + float→FP4 RNE/saturate/NaN) **23/0 all 6 backends**; `GenericPrecision` (Half/bf16/FP4 scalar relu) 30/0; `AcceleratorRequirements` 19/0/1; no regression (`PrecisionConvert_Float8` 16/0, desktop `fp8-verify` 257/257, `bf16-f16-oracle` 65536/65536). New harness `DemoConsole -- fp4-verify` (CPU/OpenCL/CUDA bit-exact: convert 24/24, decode 16/16, relu 256/256). Radix-sort keys for `Float4E2M1` follow in a later release.
Closes the last parity gaps across the four low-precision float types (`Half`, `BFloat16`, `Float8E4M3`, `Float8E5M2`) so data-type support is feature-complete with no lingering items. Forks bump to `2.0.31`.
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.14.0-local.4</Version>
7
+
<Version>4.14.0-local.5</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.14.0 brings the four low-precision float types (Half, BFloat16, Float8E4M3, Float8E5M2) to feature-complete parity. A selectable saturating cast (FromSingle(x, saturate) / FromSingleSaturating) is available on every type for the NVIDIA-TE/OCP clamp-instead-of-overflow mode, and radix-sort is complete for all four (keys + key/value pairs, ascending + descending) on all 6 backends. It also fixes low-precision CONVERSION CORRECTNESS against the references. (1) Half (float->half) is now IEEE round-to-nearest-even on every backend (CPU + WebGPU + WebGL + Wasm), bit-exact to numpy.float16 / PyTorch / CUDA / OpenCL - it previously truncated toward zero and flushed subnormals to zero (diverging from numpy AND from CUDA/OpenCL). (2) Float8E4M3 is now bit-exact to PyTorch/JAX/ml_dtypes float8_e4m3fn: the cast + IR convert use the fn convention (finite overflow AND +-Inf -> NaN; was saturate to +-448); saturating is opt-in via Float8E4M3.FromSingleSaturating. BFloat16 was already bit-exact to ml_dtypes.bfloat16 (verified). All validated exhaustively against ml_dtypes/numpy oracles + cross-backend PMT gates. 4.13.2 is a packaging fix over 4.13.1: removes stray Wasm/repro JSON files that the Razor SDK swept into the package, and bundles the precompiled-shaders precompiler tool (tools/) that 4.13.0/4.13.1 were missing. The 4.13.x line brings full low-precision floating-point support across ALL 6 backends (CPU, OpenCL, WebGPU, WebGL, Wasm, CUDA): Half, BFloat16, and FP8 (Float8E4M3 + Float8E5M2) - including FP8 radix-sort keys (4.13.1) - plus generic INumber<T> mixed-precision kernels, PrecisionConvert, and bf16/FP8 portability to pre-Ampere CUDA cards (GTX 1080 / RTX 2060). Full per-version history with code samples: CHANGELOG.md at https://github.com/LostBeard/SpawnDev.ILGPU/blob/master/CHANGELOG.md</PackageReleaseNotes>
0 commit comments