Commit Graph
5 Commits
Author SHA1 Message Date
Omar SobhandClaude Opus 5 796b8487ad rtx-backend-cuda: native index_select / index_add — HetGAT training 2.5x, inference 4.3x
GPU Tests / CUDA Tests (12.1) (push) Skipped
GPU Tests / Metal Tests (push) Skipped
GPU Tests / Check GPU Availability (push) Successful in 0s
GPU Tests / CUDA Tests (11.8) (push) Skipped
Documentation / Build API Documentation (push) Failing after 4s
CI / Format Check (push) Failing after 12s
Documentation / Build User Guide (push) Successful in 20s
CI / Build CPU-Only (Explicit) (push) Failing after 33s
CI / Clippy Check (push) Failing after 44s
CI / Build (ubuntu-latest) (push) Failing after 2m21s
Performance Benchmarks / Run Benchmarks (push) Successful in 3m4s
CI / Build (macos-latest) (push) Failing after 12s
CI / Test (macos-latest) (push) Skipped
CI / Test (ubuntu-latest) (push) Skipped
CI / Python Bindings (maturin) (macos-latest) (push) Skipped
CI / Python Bindings (maturin) (ubuntu-latest) (push) Skipped
CI / WASM Build + Size Check (push) Skipped
CI / Distributed Training Tests (push) Skipped
CI / CI Success (push) Failing after 0s
The Backend trait's index_select and index_add have default bodies that
round-trip through host memory. That is correct everywhere and was the only
implementation CUDA had. Graph message passing is made of these two ops, so
dg-gnn's HetGAT paid a device->host->device copy per layer per pass and the
RTX 5060 Ti sat at ~10% utilisation during training.

Design follows rtx-backend-metal's ops::index: gather is one thread per output
element; scatter-add walks the CSR of the adjoint selection matrix S^T, built
host-side by counting sort, so it needs NO atomics and is deterministic with
duplicate indices — the training loss is bit-identical to the host reference.
Device index buffers are cached per thread keyed by the exact index list, so a
static graph topology uploads once. Two small NVRTC kernels; no cuSPARSE.

Measured on dg-gnn, Harris 42,955 links, v8 recipe, RTX 5060 Ti:

  training batch 8      9,042 -> 3,562 ms/step   (2.5x)
  inference single p50   55.4 ->  12.9 ms        (4.3x)
  inference batch 8       257 ->    20 ms/scen   (13x; batching helps again)
  GPU utilisation       median 10% -> 21%, p90 17% -> 43%

Tests: gather with repeats, scatter-add with duplicates and untouched rows,
the adjoint identity <S x, y> == <x, S^T y> (what autograd relies on), a
hub-heavy pattern against the host reference, and the range-check panic.
rtx-backend-cuda --features cuda: 60 + 16 passed, 0 failed.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-11 23:09:01 -05:00
Omar SobhandClaude Opus 5 4f7b350d96 rtx-backend-cuda: transpose of tall tensors failed to launch, and the generic permute was an identity copy
CI / Build CPU-Only (Explicit) (push) Failing after 7s
Documentation / Build User Guide (push) Successful in 7s
CI / Format Check (push) Failing after 1m5s
CI / Build (ubuntu-latest) (push) Failing after 6m42s
Documentation / Build API Documentation (push) Failing after 6s
CI / Clippy Check (push) Failing after 7m18s
Performance Benchmarks / Run Benchmarks (push) Successful in 7m21s
CI / CI Success (push) Failing after 0s
CI / Build (macos-latest) (push) Failing after 9s
CI / Test (macos-latest) (push) Skipped
CI / Test (ubuntu-latest) (push) Skipped
CI / Python Bindings (maturin) (macos-latest) (push) Skipped
CI / Python Bindings (maturin) (ubuntu-latest) (push) Skipped
CI / WASM Build + Size Check (push) Skipped
CI / Distributed Training Tests (push) Skipped
Found by running dg-gnn's HetGAT training on an RTX 5060 Ti: the first backward
pass panicked in transpose_2d with CUDA_ERROR_INVALID_VALUE. The tensor was a
[4,211,136 x 1] gradient. The tiled kernel maps rows onto grid.y, and CUDA caps
grid.y at 65,535 blocks, so anything past ~2.1M rows was rejected at launch.
Inference never hit it — the forward pass has no transposes.

Three fixes, each tested on the GPU:

  - A row or column vector transposes to itself in memory ([N,1] and [1,N] are
    the same N floats). swap_dims now shares the buffer and swaps the shape; no
    kernel. This is the case that actually failed.
  - transpose_2d_gpu hands matrices with rows/32 > 65,535 to the 1-D generic
    permute, whose grid.x allows 2^31-1 blocks.
  - transpose_generic_gpu passed the INPUT's strides (swapped) as the kernel's
    output_strides — but the kernel DECODES each flat output index with those,
    so they must be the contiguous strides of the output shape. For a 2-D input
    that was [1, cols], which decodes every index to itself: the "permute" was
    a plain copy. Verified against the original code — a [2,3,4] swap_dims(0,2)
    returned b[1][0][0] = 12.0 where 1.0 is correct. Every higher-D dim swap
    went through this path; nothing had checked it numerically.

Also stamps kernel outputs with the contiguous strides of their new shape
rather than the input's strides swapped. Nothing outside ops/shape.rs reads
strides today, so that was latent, but is_contiguous() now tells the truth.

rtx-backend-cuda --features cuda: 55 + 16 passed, 0 failed (was 51 + 16; four
new tests, one of which fails on the original code for each bug above).

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-11 21:42:27 -05:00
osobhandClaude Sonnet 5 4aaa36a57a style: cargo fmt --workspace (whitespace/wrapping only, no semantic change)
Whole-workspace rustfmt pass picked up while iterating on Mamba GPU
backward work. Verified formatting-only via diff sampling; no logic
changed.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-10 07:09:36 -07:00
Omar SobhandClaude Sonnet 4.6 228137555f fix(gaps): G0/G2/G5/G8 — eliminate unimplemented! panics, re-enable rtx-distributed, rtx-tts, fix multimodal forward
G0 (Critical): Replace 45 unimplemented!() panics across three GPU backends
- rtx-backend-cuda: sin/cos/tanh via PTX, relu/sigmoid/leaky_relu/elu via activation.rs,
  pow/clamp/gt_scalar via unary.rs, var/var_dim host-side, conv2d/max_pool2d/avg_pool2d
  CPU fallback in new ops/conv.rs; new PTX kernels in element_wise.cu
- rtx-backend-rocm: all 15 ops via CPU round-trip (to_vec → compute → from_slice)
- rtx-backend-sycl: all 15 ops via CPU round-trip (to_host → compute → from_data)

G2 (High): Re-add rtx-distributed to workspace
- Vendor 4 minimal RNCCL stub crates at crates/vendor/rnccl/*
- Update rtx-distributed RNCCL path deps to point at stubs (../../../../RNCCL/* → ../../vendor/rnccl/*)
- Remove rtx-distributed from workspace exclude list, add to members

G5 (Medium): Re-enable rtx-tts (213 tests restored)
- Fix 15 rtx-nn API drift issues: LayerNorm::new, Conv1d::from_config, Conv1dPadding::Zeros,
  Dropout::new(p, device), tensor methods (relu/tanh/sigmoid/cat/stack), squeeze(Some(n)),
  to_vec() turbofish removal, Tensor::randn with &[...] slices

G8 (Low): Quantum stubs + multimodal forward bug
- rtx-timeseries: remove dead quantum/neuromorphic TODO comment blocks (no module files exist)
- rtx-multimodal/fusion/transformer.rs: wire TransformerBlock loop in forward()
- rtx-multimodal/fusion/strategies.rs: wire bottleneck_layers loop in forward()
- rtx-transformers/architectures/transformer_block.rs: add forward() method (pre-norm residuals;
  full attention+FFN pending when those sub-layers are wired)

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-06-26 13:40:23 +00:00
redclawsystems 4d88dc0584 Initial commit 2026-03-04 00:08:42 +00:00