OxiCUDA 0.4.0 Release
[0.4.0] - 2026-07-01
This release is an on-device validation pass: for the first time, hand-written PTX kernels across more than 60 crates were JIT-compiled and executed on real NVIDIA GPU hardware (an RTX A4000, sm_86, CUDA 12.4) rather than only checked for CPU-logic parity. This surfaced and fixed dozens of genuine bugs that no amount of CPU-side testing could have caught — kernels that never compiled (ptxas rejected them outright), kernels that compiled but computed the wrong thing (register shadowing, base-2/base-e mixups, races), and kernels that were still bare stubs behind a real, tested CPU reference implementation. Every fix was verified fail→revert→pass on the actual device. Alongside the validation sweep: several algorithms went from partial/proxy PTX implementations to full ones (P1 FEM assembly, NODE tree inference, soft-MoE dispatch, 3D Gaussian splatting projection/SH), a few new modules landed (variable-depth NODE trees, TabR-style retrieval, preconditioned CG, GPT-NeoX RoPE), and analytic test coverage was added for dozens of previously-untested modules.
Added
- On-device GPU validation harness: a feature-gated
gpu-testsCargo feature plus asrc/gpu_tests.rsmodule per crate, JIT-compiling each crate's hand-written PTX viaModule::from_ptx, launching it on a live CUDA device, and asserting numerical equivalence to a CPU oracle. Rolled out workspace-wide (more than 60 crates); every test skips gracefully when no device is present. See Fixed below for what it caught. - Crates that ran clean on the very first on-device pass (JIT-loaded and matched their CPU oracle with zero bugs found):
oxicuda-pinn(7 kernels),oxicuda-bayes(7),oxicuda-federated(7),oxicuda-continual(7),oxicuda-peft(7),oxicuda-meta(7),oxicuda-tn(7),oxicuda-sketch(7),oxicuda-graphalg(7),oxicuda-cvx(7),oxicuda-gen(6),oxicuda-adversarial(7),oxicuda-hdc(7) — 42+ kernels across 13 crates with no defects on first real-hardware execution.oxicuda-pde(7) andoxicuda-numeric(7) likewise matched cleanly but each surfaced one honestly-documented (not fixed) caveat:pde'sfem_assemble_kernel(pre-completion, see below) was confirmed to do only a signed-triangle-area scatter;numeric'sbessel_recurrencealiases the next point'sJ_0when multiple points share a launch (documented, validation scoped to the single-point calling convention). oxicuda-pde:fem_assemble_kernelcompleted from a partial stub (per-element signed-area scatter into one matrix entry) to a full unconstrained dense P1 stiffness assembly — the 3×3 localK_ij = (1/(4·Area))·(b_i·b_j + c_i·c_j)per element, atomically scattered into the dense global matrix. Validated element-wise against the crate's ownp1_local_stiffnessto 1e-4 rel / 1e-5 abs.oxicuda-tabular:sparsemax_kernelreplaced a dead threshold pass with the exact O(D²) Martins & Astudillo largest-support search;quantile_norm_kernelreplaced a 2-bucket heuristic with true empirical-CDF linear-scan + interpolation;node_tree_eval_kernel(previously hardcoded to 2 leaves, ignoringdepth) now runs the full multi-level NODE tree with per-level entmax-1.5 bisection and a2^depth-leaf mixture. Validated againstsparsemax/QuantileTransformer::transform/NodeTree::forwardat 1e-4–1e-5. Also new:VarObliviousLayer(variable-depth NODE oblivious trees via outer-product leaf gating) andTabRecordLayer(TabR-style retrieval: encode → scaled −L2 similarity → entmax attention → convex combination), reusing the crate's entmax/entmoid/sparsemax simplex code (19 tests).oxicuda-moe:soft_moe_dispatch_kernelcompleted from a first-slot-only proxy to the real 3-pass slot-softmax dispatch matrixD[t,s] = softmax(x·Φ/√d)over all slots. Validated againstSoftMoeRouter::dispatch_weightsto 5e-4, every output row confirmed to sum to 1.oxicuda-geometry3d:project_kernelnow emits the full EWA 2D covarianceΣ_2d = J·R·Σ_3d·Rᵀ·Jᵀ + 0.3·I(previously never written);sh_eval_kernelnow evaluates all 9 L=0..2 spherical-harmonic terms per RGB channel (previously a reduced 5-term basis). Validated againstproject_gaussian/Gaussian3d::sh_coloron the A4000.oxicuda-recsys: implemented 4 previously-empty-loop stub kernels —embedding_lookup,dot_score,bpr_gradient,lightgcn_propagate— now real, validated bit-exact / to ~1e-4 againstBpr/LightGcnCPU references. The remaining PTX surface (softmax_topk,negsample_uniform) is documented as still-stub with loud STUB/PTX-BUG doc comments designed to fail the day each is implemented for real.oxicuda-webgpu:naga_tests.rs— real WGSL parse+validate (naga::front::wgsl::parse_str+valid::Validator) across all 15 shader generators (31 tests), replacing prior substring-only shader checks.oxicuda-pinn: hand-written pure-Rust FFT (iterative radix-2 Cooley–Tukey + Bluestein chirp-z for arbitrary/prime N) replacing the FNO spectral path's O(N²) brute-force DFT; wired into 1D + separable-2Dspectral_conv, zero rustfft/oxicuda-fft dependency (fno_3d's DFT is a noted follow-up).oxicuda-nas:LatencyLut::to_bytes/from_bytes— a dependency-free little-endian persistence format (magicLLUT+ version + stableOpKinddiscriminants), 7 tests including round-trip identity across all 8OpKindvariants.oxicuda-cvx: preconditioned conjugate gradient —pcg_solve/pcg_solve_counted/cg_solve_countedplus aPreconditionertrait withIdentityPrecond/JacobiPrecond(Jacobi cuts a κ=1e4 diagonal system from 6 CG iterations to 1).oxicuda-blas,oxicuda-ptx: new PTX kernel templates for broadcast bias-add and a numerically-stable causal (masked) softmax, F32/F64.oxicuda-dnn: GPT-NeoX half-split partial-rotary RoPE (NeoXRopeConfig,apply_rope_neox_half_split) alongside the existing GPT-J/RoFormer interleavedRope, plus a RoPE-NeoX attention integration.oxicuda-ptx,oxicuda-metal,oxicuda-memory: new f64 math-intrinsic codegen module (body_builder/math_f64.rs), Metal backend function/type additions, anddevice_bufferhelpers.- Large-scale analytic test-coverage expansion for previously zero-coverage modules (property-based/closed-form assertions, not smoke tests):
oxicuda-rlhf(kl_control, alignment metrics, PPO GAE rollout, SFT/reward/preference losses — 54 tests),oxicuda-recsys(popularity_neg + a 116-test suite across 16 models: BERT4Rec, SASRec, GRU4Rec, PLE, MMoE, ESMM, DeepFM, AutoInt, Wide&Deep, ALS, NMF, NGCF, LightGCN, NCF, Two-Tower, hard-neg sampling),oxicuda-peft(merge/p-tuning-v2 + a 67-test suite across 9 adapter variants),oxicuda-meta(few-shot/linear-head + a 69-test suite across the MAML family),oxicuda-numeric(8 Gauss-Patterson exactness tests to degree 46),oxicuda-evol(8 CMA-ES Jacobi-eigensolver spectral-identity tests),oxicuda-solver(16 PDE/ODE tests with measured O(h²) convergence),oxicuda-ann(43 tests across HNSW/kNN-graph/IVF/IVFPQ). - Test suite expanded to 38,093 passing tests (workspace-wide,
--all-features; 37,166 with default features), up from 36,984 at 0.3.0.
Changed
oxicuda-solver:syevd(symmetric eigensolver) and the blocked Householder QR / one-sided-Jacobi SVD device paths previously launched an incomplete GPU kernel and read back fabricated (never-computed) values. Replaced with an explicit, documented exact-CPU host fallback — no GPU acceleration yet, pending on-device follow-up — rather than silently returning wrong results.oxicuda-ssl:barlow_cross_corr_wgmma,nt_xent_softmax_warp, andgather_features_bulkare now documented as intentionally Hopper/Blackwell-only PTX (wgmma,redux.sync, TMA); each has an on-device-confirmed portable scalar fallback for Ampere and older.
Fixed
- Register-shadowing of CUDA's built-in special registers (
.regdeclarations literally named%tid/%ntid/%ctaid/%warpid, clobbering the special registers like%tid.xactually read from) — the single most common defect class this pass found, affectingoxicuda-primitives,oxicuda-train(all 9 optimizer kernels),oxicuda-ann(hnsw_neighbor_eval/ivf_assign/topk_select),oxicuda-rl(all 5 kernels),oxicuda-dist-infer(all 5 kernels), andoxicuda-timeseries(all 7 kernels, plus a special register used directly as amadoperand). All renamed to non-colliding register names. - Base-2 (
ex2.approx/lg2.approx) used where the math needs base-e — silently plausible, genuinely wrong:oxicuda-survival(Cox risk/score/info, ~18–30% off),oxicuda-seq(HMM forward log-sum-exp, ~30% off),oxicuda-ot(Sinkhorn/unbalanced log-sum-exp, ~20% off),oxicuda-rlhf(BT/DPO/KTO losses),oxicuda-nerf(volume_render's alpha compositing),oxicuda-gnn(softmax_edge, masked by softmax's own scale-invariance — only a base-e CPU oracle caught it), andoxicuda-audio(ctc_alpha_kernel, bundled with two other defects below). All fixed with the correctlog2(e)/ln(2)scaling. - Kernels that never compiled at all — invalid PTX rejected outright by
ptxas: undeclared/out-of-range registers (oxicuda-multimodal'sbilinear_pool/temporal_pool,oxicuda-audio'sctc_alpha_kernel,oxicuda-quant's all 5 kernels,oxicuda-moe'sexpert_dispatch_kernel), a duplicate register declaration (oxicuda-geom2d'spoint_in_aabb), mid-function.regdeclarations (oxicuda-distill'sat_pool_kernel/gram_matrix_kernel), a missing.reg .predentirely (oxicuda-recsys'sals_update_step), illegal scaled-register shared-memory addressing (oxicuda-ann'stopk_select,oxicuda-infer'slogits_softmax,oxicuda-causal'sexpm_pade_kernelacross dozens of sites — the latter also stored immediate literals directly viast.shared.f32, whichstcannot take as a source operand), the[smem]bracket form used as arithmetic instead of load/store (oxicuda-lm'srms_norm/causal_attn_softmax), a non-existentatom.exch.s32(oxicuda-tda'sboundary_reduce, needs.b32), a non-existentcos.approx.f64/lg2.approx.f64(oxicuda-fft'sprecompute_window,oxicuda-evol'sgaussian_mutate_kernel), an unsupported 4-bytecp.async.cgtransaction (oxicuda-cs'siht_step_cp_async, needs.cafor sub-16-byte transactions — a separate deadlock from out-of-range threads skippingbar.syncwas fixed in the same kernel), a malformed branch label (oxicuda-sparse'sspmv_bsr), and invalid braced predication plus nonexistent f64 SFU forms (oxicuda-privacy, 6 of 7 differential-privacy kernels). All now compile and are ptxas-verified on sm_86. - Kernels that compiled but computed the wrong thing:
oxicuda-manifold'sknn_topkwas correct only for k=1 (missing the ascending bubble-up pass for k>1);oxicuda-vision'sbilinear_interp/roi_alignused the non-existentfloor.f32(replaced withcvt.rmi.f32.f32);oxicuda-stats'smean_var/rank_assignwere missing the.rnrounding qualifier oncvt.f32.u32;oxicuda-quantum's statevector simulator had 8 stacked defects (partial 4×4 gate matrix-vector products, wrong bit-insertion masks, an unguarded swap race, divergent-laneshfl.sync, wrong Taylor-series hex-float constants) — essentially every operation was wrong;oxicuda-anomaly'slof_reach_dist_kernelhad a loop-index register clobber that collapsed everyreach_disttokd_j;oxicuda-mamba'sparallel_scanused the wrong shuffle direction (100% wrong) andwkv_forwardused the wrong softmax pivot (42.6% error);oxicuda-audio'srel_pos_bias_kernelhad an unsigned-underflow clamp bug andstats_pool_kernelhad a 32-lane write race;oxicuda-nas'sgumbel_softmax_kernelusedlog2(e)whereln(2)was needed (its reciprocal, ~2.08× error);oxicuda-geometry3d'ssh_eval_kernelreferenced a register past its declared bank and dropped adxfactor from every channel'sc1·Y11term;oxicuda-moe'sexpert_ffn_kernelGELU tanh approximation was missing a factor of 2 in its exponent;oxicuda-infer's flagshippaged_attentionhad 5 stacked defects (invalid 64-bitmul.wide.u32, a partial dot product instead of the full Σ_d, V read through the K pointer, base-2 softmax, wrong GQA head mapping) andrope_applydropped a sign term plus used an impreciselog2(10000)constant. oxicuda-solver:lu.rs'slaunch_gemm_updateswapped the grid X/Y axes against the actual row/column mapping (dropping part of the GEMM update on non-square trailing tiles), and its Padé matrix-exponential kernel always loaded f64 coefficients even in the f32 variant — both fixed. Separately, the LU (panel_lu/trsm_unit_lower/gemm_update/pivot_swap) and Cholesky (panel_cholesky) kernels were literalret;stub bodies performing no factorization at all — implemented with realbar.sync-staged panel/trailing updates, validated by two new on-device test suites including an independent splitmix64-seeded adversarial harness.oxicuda-rand: AES round-key words needed.swap_bytes()for the device's endianness;mrg32k3a/philox/xorwow's Box-Muller kernels shared one f32/f64 register pool, corrupting Gaussian sampling on all three engines; 4philox_optimizedbranch targets were missing the$label sigil.oxicuda-signal:dct2_permute/dct3_pretwiddle/dct3_unpermute/fir_directused illegal brace predication;fir_direct's bounds guard was an always-falsesrc > u64::MAX(silently zeroing all output);dct3_pretwiddle/dct4_postscaleemitted f32 immediates into f64 instructions.oxicuda-ssl:random_mask_kernelhad a spurious×0.5roughly doubling the effective drop probability.oxicuda-tabular:feature_tokenize_kerneladdressed its weight/bias rows with stride 1 instead offeat*embed_dimand never looped over the embedding dimension.oxicuda-rlhf:dpo_loss_kernel's grid-stride accumulation clobbered the register holdingbetawith an atomic's return value;ppo_rlhf/ppo_step.rs's per-step value-loss loop (a CPU-side bug, found by the new test suite) readvalues[0]for every step instead of the current step's value.oxicuda-ann:ivf/ivf.rssearch(CPU-side, found by the new test suite) indexed insertion-ordered vectors with a list-traversal counter instead of per-list storage, scoring against the wrong stored vector wheneveradd()calls interleaved across coarse lists.oxicuda-recsys: (CPU-side, found by the new test suite)multitask/ple.rsfed shared experts at layer>0 the wrong-length input from the previous layer;factorization/als.rs'sgauss_jordanhad a redundant row-swap that skipped exchanging column 0 whenever the pivot was off-diagonal.oxicuda-blas(GEMM),oxicuda-dnn(LayerNorm, and separatelyimplicit_gemm/conv1x1/depthwisewhich were comment-only stubs with no arithmetic),oxicuda-sparse(f64 CSR SpMV, including an illegal 64-bitshfl.sync.down.b64split into.b32halves, and the mixed-precision SpMV FP64 path): a shared invalid-PTX bug class — an.f32-declared register bank and/or single-precision zero literal used in.f64instructions. Root-caused once inoxicuda-ptx'sPtxType(precision-correct zero-literal encoding + correctly-roundedcvtselection) and applied across all affected sites; LayerNorm's.maxntiddirective was also misplaced inside the kernel body with a stray semicolon.oxicuda-snn: theatansurrogate-gradient kernel was off by π² (α·π/(1+x²)instead ofα/(π·(1+x²))), affecting every SM target sm_75–sm_100.oxicuda-webgpu:conv2dWGSL codegen named a bufferfilter, a reserved WGSL keyword, failing naga parsing outright — renamed tokernel_w.oxicuda-metal: cleared 2 clippy warnings inmemory.rs(missingdead_codecfg-gate, a redundant explicitdrop).
Full Changelog: v0.3.0...v0.4.0