Commit Graph

4015 Commits

Author SHA1 Message Date
jgrusewski
dd4255c6c9 fix: update 5 ml tests for 7-level ExposureLevel
- Rename test_c2_dqn_default_num_actions_is_9 → _is_7, assert 7
- PPO adapter tests: NaN-safe direction assertions (fresh model = random weights)
- Curriculum: NUM_ACTIONS 5→7, phase1_mask 7-element (ShortHalf/Flat/LongHalf),
  update all index/count assertions for ShortSmall..LongFull layout
- Fixes 903 pass / 0 fail (was 898 pass / 5 fail)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 12:21:52 +02:00
jgrusewski
3696cb475b fix: update action reporting from 9-level to 7-level ExposureLevel
ShortSmall=0, ShortHalf=1, ShortFull=2, Flat=3, LongSmall=4, LongHalf=5,
LongFull=6. Updates all array sizes, bounds checks, names, and distribution
logic across gpu_monitoring, monitoring, training_loop, metrics, and financials.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 12:12:18 +02:00
jgrusewski
1e133e4ca1 feat: enable PopArt + tau coupling + verify PER/Sharpe reset between folds
Task 3: Enable PopArt reward normalization (default true, all 3 TOML configs,
wiring confirmed in fused_training.rs submit_forward_ops_main()).
Task 4: Couple PopArt variance with tau reset — add prev_popart_var to
FusedTrainingCtx, read_popart_var() to GpuDqnTrainer, read_popart_variance()
+ should_reset_tau() to FusedTrainingCtx, tau reset injected at epoch boundary
in training_loop.rs after log_phase_timing().
Task 5: Add best_sharpe/best_epoch/best_val_loss reset to reset_for_fold() so
each walk-forward fold competes independently. Also wire v8 reward fields
(popart_enabled, micro_reward_scale, td_lambda, max_trace_length,
hindsight_fraction, hindsight_lookahead) through training_profile.rs apply_to().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 12:02:29 +02:00
jgrusewski
a401f03f9a fix: remove 30% Flat floor + fix magnitude masking — ABI exploration replaces it
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 11:56:32 +02:00
jgrusewski
448b61d095 refactor: collapse 9-level to 7-level ExposureLevel — eliminate degenerate Flat variants
The 4-branch DQN (direction x magnitude) had 3 degenerate variants
(Short25, Flat, Long25) that all mapped to 0.0 target exposure when
direction=Flat, causing 82% Flat collapse. Collapse these into a
single Flat variant, giving 7 levels (ShortSmall/Half/Full, Flat,
LongSmall/Half/Full) and 63 total factored actions (7x3x3).

- ExposureLevel enum: 9 variants -> 7 (add direction/magnitude/from_dir_mag)
- FactoredAction: 81 -> 63 total actions, from_index/to_index updated
- DQN epsilon-greedy: use from_dir_mag() instead of dir*3+mag indexing
- DQN config: num_actions default 9 -> 7
- PPO action space: 45 -> 63 actions, action masking updated
- Signal adapter CUDA kernel: 5-bin -> 7-bin exposure aggregation
- All tests updated for new variant names and index ranges

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 11:54:09 +02:00
jgrusewski
55be1776b5 plan: ABI Foundation — 7-level exposure + PopArt + tau coupling + PER clear (6 tasks, 27 steps)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 11:28:59 +02:00
jgrusewski
553289545a spec: Autonomous Branch Intelligence (ABI) — fix DQN action collapse
10-component design to fix 82% Flat/Small action concentration:
1. Collapse degenerate 9→7 level exposure space
2. Per-branch reward decomposition (direction/magnitude/order/urgency)
3. Hindsight action relabeling for magnitude
4. Position-aware temporal exploration with per-branch epsilon
5. IQN quantile spread as anti-collapse signal
6. Activate PopArt + couple with tau reset
7. Feed the gradient vaccine with diverse batches
8. Per-branch bottleneck widths
9. Ensemble variance at inference
10. Clear PER between folds

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 11:23:23 +02:00
jgrusewski
bdcc3b7d30 perf: cublasLt RELU_BIAS epilogue fusion for trunk + branch hidden GEMMs
Fuses GEMM + bias-add + ReLU into a single cublasLtMatmul kernel via
CUBLASLT_EPILOGUE_RELU_BIAS. Eliminates 7 separate add_bias_relu
kernel launches per forward pass (3 trunk + 4 branch hidden layers).

Creates separate cached descriptors with epilogue enabled at init time.
Falls back to separate kernels if the epilogue heuristic isn't available.
Bias pointer set dynamically per-call via set_matmul_desc_attribute.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 10:57:57 +02:00
jgrusewski
7c34003f03 perf+fix: cuBLAS descriptor caching, per-branch workspace, shrink-perturb fix
Performance:
- Cache cuBLAS descriptors: pre-create matmul_desc + layouts + algo at init.
  requestedAlgoCount=3 for better algorithm selection. Zero per-GEMM overhead.
- Per-branch workspace: 4 × 32MB separate workspace buffers for multi-stream
  branch dispatch. Eliminates workspace contention on parallel execution.

Training stability:
- Remove hardcoded shrink-perturb that fired every epoch on short runs (3-5 epochs).
  With epochs=5, interval = epochs/4 = 1 → fired every epoch, destroying epoch 1
  learned weights. This caused Sharpe to collapse from +0.60 to -0.29 after epoch 1.
- Phase 3 shrink-perturb now uses config values (was hardcoded alpha=0.9, sigma=0.01).
- The config-defined shrink_perturb_interval=20 now controls all shrink-perturb timing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 10:40:56 +02:00
jgrusewski
74f27d18f3 fix: revert workspace 16MB→32MB — H100 CUDA 13.0 CUBLAS_STATUS_NOT_SUPPORTED
The backward GEMM heuristic on H100 with CUDA 13.0 requires 32MB
workspace for TF32 algorithm selection. 16MB causes
CUBLAS_STATUS_NOT_SUPPORTED on dW_only (m=256,n=128,k=16384).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 10:19:35 +02:00
jgrusewski
1e5ed3bde1 perf: target branch parallelism + attention Q,K,V cache + workspace reduction
Three optimizations targeting the 345ms mega-graph bottleneck:

1. Target forward multi-stream branches (est -15ms):
   Replaced single aliased tg_h_b_scratch with 4 separate buffers.
   Target forward now uses fork-join multi-stream dispatch (same as
   online forward) — 4 branch GEMMs run in parallel instead of serial.

2. Attention Q,K,V projection caching (est -10ms):
   Forward kernel saves Q,K,V projections to a 14MB buffer.
   Backward kernel reads saved projections instead of recomputing
   from weights — eliminates 12 O(D) inner products per sample.

3. cuBLAS workspace reduction (32MB → 16MB):
   Sufficient for H100 TF32 tile sizes at our matrix dimensions.
   Reduces L2 cache pressure from workspace allocation.

Combined with IQN h_s2 reuse from prior commit: target 345ms → <300ms.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 10:08:55 +02:00
jgrusewski
a93c35a614 perf: IQN reuses DQN Pass 2 target h_s2 — eliminates redundant trunk forward
IQN was recomputing target h_s2 via iqn_trunk_forward_kernel using the
same target weights on the same next_states that DQN Pass 2 already
computed into tg_h_s2_buf. Now IQN reads from the pre-computed buffer
via a DtoD copy (negligible) instead of re-running 2 cuBLAS GEMMs.

Expected: -15ms GPU time on H100 (batch=16384, shared_h2=256).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 09:53:26 +02:00
jgrusewski
3b2bf8d993 fix: remove in-graph sub-phase events (CUDA_ERROR_INVALID_VALUE)
Events recorded during CUDA graph capture cannot be queried with
cuEventElapsedTime after graph replay — the graph creates internal
copies. Reverted to original mega-graph capture structure.

Sub-graph timing fields kept in PhaseEvents for future use with
split-graph diagnostic mode or nsys profiling.

Also kept submit_loss_and_grad_ops() extraction and pub(crate) visibility
on launch_cublas_forward/backward for future per-phase graph splitting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 02:41:41 +02:00
jgrusewski
ef5be1b7a3 perf: add sub-graph phase events inside mega-graph capture
Split fwd_bwd timing into 5 sub-phases: spectral, forward, loss,
backward, aux. Events recorded during graph capture replay with the
graph on every step.

Also extract submit_loss_and_grad_ops() from submit_forward_ops_main()
and make launch_cublas_forward/backward pub(crate) for sub-graph timing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 02:31:03 +02:00
jgrusewski
a04fcb31f5 fix: cuEventElapsedTime → cuEventElapsedTime_v2 for CUDA 13.0 (H100)
CI builder uses CUDA 13.0 cudarc which exports _v2 suffix.
Local CUDA 12.x has both names but CI only resolves _v2.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 02:06:58 +02:00
jgrusewski
b519ec8472 cleanup: eliminate remaining bf16 references from GemmEx + NoisyLinear
- linear.rs: gemm_ex_bf16 → gemm_ex_f32 (function + all call sites)
- stream_ops.rs: gemm_ex_bf16 → gemm_ex_f32
- noisy_layers.rs: remove bf16 comments, update GemmEx calls
- noisy_kernels.cu: update kernel comments for f32
- branching.rs: update test comments (was "BF16 weight copy")

Pure f32/TF32 pipeline — zero bf16 code paths remain.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 01:57:31 +02:00
jgrusewski
a642fe5ad9 fix: deadlock in epoch boundary — remove cuStreamSynchronize, fix Q-diagnostics
Root cause: cuStreamSynchronize blocked the thread, preventing tokio
single-threaded runtime from progressing RwLock .write().await calls.

- Remove cuStreamSynchronize from training loop (stalls pipeline)
- Move log_phase_timing() after process_epoch_boundary (DtoH syncs stream)
- compute_epoch_q_diagnostics takes &mut DQNAgentType param (no re-lock)
- Disable Q-value gap diagnostics (deadlock in single-threaded runtime)
- smoke_trainer helpers: always set fxcache dir
- test_no_hang_single_epoch: use fxcache direct loading

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 01:35:13 +02:00
jgrusewski
7341491776 fix: fxcache always-on in smoke tests + cuStreamSynchronize before event timing
- smoke_trainer/smoke_trainer_with: always set with_feature_cache(feature_cache_dir())
- Add load_smoke_fxcache() + init_trainer_from_fxcache() helpers for direct loading
- test_no_hang_single_epoch: use fxcache directly (was slow DBN parsing)
- cuStreamSynchronize before log_phase_timing (was CUDA_ERROR_NOT_READY)
- Fix evaluation engine tests for 9-level ExposureLevel mapping

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 01:11:20 +02:00
jgrusewski
82f64551e6 fix(critical): eliminate bf16 remnants from CUDA reduction kernels
Root cause of 61 test failures: bf16→f32 migration missed two sites:

1. reduction_kernels.cu: atomicCAS loops used `unsigned short` (2 bytes = bf16)
   on float* data. With f32 (4 bytes), the 2-byte CAS corrupted adjacent memory
   → CUDA_ERROR_ILLEGAL_ADDRESS. Fixed: use `unsigned int` + __float_as_uint().

2. reductions.rs: shared memory allocated at `threads * 2` (bf16 = 2 bytes)
   instead of `threads * 4` (f32 = 4 bytes) in 5 kernel launch sites.
   Kernels wrote past shared memory → undefined behavior.

Also fix evaluation engine tests for 9-level ExposureLevel mapping
(Long50 = 0.25 not 0.5, Short50 = -1.0 = Short×Full).

Result: 287/287 ml-dqn tests pass (was 226/287).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:42:26 +02:00
jgrusewski
ee6088eb53 fix: 4-branch inference indexing + GpuTensor→CudaSlice API boundaries
Bug fixes:
- select_action_inference: exposure = dir*3+mag (was using dir only),
  order = greedy[2] (was [1]), urgency = greedy[3] (was [2])
- select_action_with_confidence: same 4-branch indexing fix,
  random path 0..5 → dir*3+mag (9 exposure levels)

GpuTensor elimination at API boundaries:
- batch_branching_q_values returns (CudaSlice<f32>, ×3) via into_parts()
- batch_q_values, forward return CudaSlice<f32> directly
- batch_greedy/softmax_actions return Vec<u32> (no GpuTensor wrapping)
- Delete extract_cuda_f32! macro — callers use CudaSlice directly
- GpuActionSelector already uses raw CudaSlice — now the whole
  action selection chain matches

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:13:33 +02:00
jgrusewski
e265768cb3 cleanup: delete dead CPU replay buffers, DQNAgentType::Standard, add CUDA event profiling
- Delete 7 dead files: prioritized_replay.rs, prioritized_replay_staleness.rs,
  replay_buffer.rs, hindsight_replay.rs, rainbow_agent.rs, checkpoint.rs,
  strategy_dqn_bridge.rs (-4,760 lines)
- Rewrite replay_buffer_type.rs: ReplayBufferType enum → StagedGpuBuffer struct
  (GPU PER is the only replay path, no CPU fallbacks)
- Strip agent.rs to data types only (TradingState + AgentMetrics)
- Convert DQNAgentType from enum to struct wrapping RegimeConditionalDQN
  (Standard variant was never constructed, 43 dead match arms removed)
- Remove dead CPU methods: store_experience, fused_post_step,
  fused_post_step_no_ema, adaptive_buffer_resize, refresh_stale_per_priorities
- Add always-on CUDA event per-phase profiling (8 events, 4 phases:
  upload/fwd_bwd/adam/per_update) with Drop cleanup and error checking
  to identify 329ms/batch H100 bottleneck

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:13:09 +02:00
jgrusewski
f6991dd8b2 plan: dead code cleanup + GPU per-phase CUDA event profiling (6 tasks, 32 steps) 2026-04-10 22:23:16 +02:00
jgrusewski
1b5af8e9f3 spec: dead code cleanup + GPU per-phase CUDA event profiling 2026-04-10 22:16:24 +02:00
jgrusewski
74392e3744 fix(critical): 16-byte align weight pointers for cublasLtMatmul FAST_TF32
Root cause: weight tensors packed sequentially in the flat params buffer
had non-aligned start offsets when preceding tensors had odd element counts
(e.g. bias of 51 atoms = 204 bytes, 204 % 16 = 12). cublasLtMatmul with
CUBLAS_COMPUTE_32F_FAST_TF32 requires 16-byte aligned buffer pointers.

Fix: pad each tensor to 4-element boundary (16 bytes) in both
f32_weight_ptrs_from_base (pointer computation) and compute_total_params
(buffer allocation). Added align4() and padded_byte_offset() helpers,
fixed shrink_perturb skip range and bottleneck gradient offset.

Switched compute type: CUBLAS_COMPUTE_32F → CUBLAS_COMPUTE_32F_FAST_TF32
(forward + backward). Explicit TF32 tensor core path, required by cuBLAS
13.0 on H100 SM90.

Deleted dead bf16_weight_ptrs function.
19/19 smoke tests pass on RTX 3050.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 21:38:14 +02:00
jgrusewski
7e72cca5e2 fix: upgrade ci-builder to CUDA 13.0 — match H100 runtime (Driver 580) 2026-04-10 21:19:28 +02:00
jgrusewski
d5fba5558d fix: update cudarc comment — vendored via patch.crates-io for H100 cublasLtMatmul fix 2026-04-10 21:13:15 +02:00
jgrusewski
fb8b842d1f fix: rename network policy compile-and-train → train for consistency 2026-04-10 20:53:44 +02:00
jgrusewski
b62b62e14c fix: match compile-and-train network policy label for pod egress 2026-04-10 20:52:20 +02:00
jgrusewski
b8343183c2 fix: pass SHA via inputs.parameters in Argo DAG task arguments
Argo requires task output parameters to flow through DAG arguments →
template inputs, not direct {{tasks.X.outputs}} in container args.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 20:38:47 +02:00
jgrusewski
445c2197f2 feat: unified Argo train workflow — replace 7 templates with 1
New: train-template.yaml with smart caching:
  - ensure-binary: checks /data/bin/{sha}/ on PVC, compiles only on cache miss
  - ensure-fxcache: runs precompute only if cache doesn't exist
  - gpu-warmup: parallel autoscale during compile
  - hyperopt → train-best → evaluate → upload-results

Deleted 7 redundant templates:
  - compile-and-train-template.yaml
  - train-dqn-template.yaml
  - train-baseline-rl-template.yaml
  - train-supervised-template.yaml
  - training-workflow-template.yaml
  - precompute-features-template.yaml
  - train-ppo-template.yaml

Deleted: scripts/argo-precompute.sh (absorbed into ensure-fxcache step)
Rewritten: scripts/argo-train.sh (single template, --sha for commit pinning)
Updated: kustomization.yaml

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 20:36:03 +02:00
jgrusewski
f8e0f459fc feat: unified train workflow template — cache-or-compile + cache-or-precompute
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 20:34:08 +02:00
jgrusewski
8c92db09f3 spec: Argo training pipeline redesign — one workflow, smart caching
Single train template replaces 7 overlapping workflows. Binary cache
on PVC by commit SHA, fxcache skip-if-exists. Delete 5 dead templates.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 20:26:55 +02:00
jgrusewski
8919eccbb9 cleanup: remove --bf16 flag from precompute scripts and Argo template
Binary no longer accepts --bf16 (single f32 format). Removed from:
- scripts/argo-precompute.sh
- infra/k8s/argo/precompute-features-template.yaml

PVC fxcache cleaned: deleted 2.4GB old bf16 cache from feature-cache-pvc.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 20:05:58 +02:00
jgrusewski
904a158df1 perf: eliminate f32 shadow buffers — GemmEx reads master params directly, saves 2x weight VRAM + copy overhead
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 19:52:29 +02:00
jgrusewski
6eda39b829 fix: 50-epoch overfitting test — zero hardcoded thresholds, all checks relative
Add last_epoch_loss metric. All assertions now compare the run's own metrics
against each other: convergence = loss stability (not divergence), overfitting =
best_oos_sharpe >= first_sharpe, OOS collapse = val_loss swing/magnitude ratio.

Walk-forward fold resets make epoch-1 loss unreliable for convergence comparison
(pre-trained weights), so we check stability instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 19:33:46 +02:00
jgrusewski
5fa877aaa8 fix: rewrite 50-epoch overfitting test with calculated bounds, add final_sharpe/final_val_loss metrics
- Add final_sharpe and final_val_loss to TrainingMetrics (last-epoch values)
- Rewrite test_walk_forward_no_overfitting_50_epochs: all checks are relative
  to the run's own metrics — no hardcoded thresholds
- Checks: finiteness, gradient health, OOS collapse ratio, IS→OOS gap ratio
- 19/19 smoke tests pass

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 19:25:50 +02:00
jgrusewski
42308b159f fix: resolve_data_dir helper for consistent relative path resolution
Extract shared resolve_data_dir() function — resolves relative data paths
against workspace root via CARGO_MANIFEST_DIR. Used for mbp10_data_dir
and trades_data_dir (was only mbp10 before, causing smoke test failures).

All 19/19 smoke tests pass with pure f32 pipeline.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 19:15:37 +02:00
jgrusewski
21abd2b0f9 fix: evaluate_baseline bf16→f32 remnants, delete old fxcache files
- Fix f32::from_f32/f32::ZERO (nonexistent) in evaluate_baseline.rs
- Eliminate redundant Vec copies (upload source data directly)
- Fix comments referencing __nv_bfloat16 in reductions.rs, training_guard_kernel.cu
- Delete 3 old bf16-format .fxcache files from test_data/

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 18:57:36 +02:00
jgrusewski
ddbad94329 cleanup: remove half crate dependency from entire workspace
half crate no longer needed — zero bf16 references remain.
Removed from: ml, ml-core, ml-dqn, ml-ppo, ml-supervised, workspace root.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 18:54:14 +02:00
jgrusewski
4842a04011 refactor: eliminate ALL bf16 from entire workspace — pure f32/TF32 pipeline
Complete bf16 elimination across all crates (ml, ml-core, ml-dqn, ml-ppo,
ml-supervised). Zero half::bf16, __nv_bfloat16, or CudaSlice<half::bf16>
references remain (verified by grep).

CUDA: All 60+ .cu kernels and .cuh headers converted to native float.
  - Half-precision intrinsics (__hmul, __hadd, __hdiv) → float operators
  - atomicAddBF16 → native atomicAdd(float)
  - bf16 wrapper functions → f32 identity passthroughs

Rust: All CudaSlice<half::bf16> → CudaSlice<f32> across 90+ files.
  - htod_f32_to_bf16/dtoh_bf16_to_f32 → htod_f32/dtoh_f32 (direct, no conversion)
  - Deleted bf16 mirror infrastructure (DuelingWeightSetBf16, alloc_bf16_mirror, etc.)
  - Renamed params_bf16→params_flat, d_value_logits_bf16→d_value_logits, etc.
  - Fixed .to_f32() sed damage on Decimal::to_f32() and rng.f32()

FxCache: Single f32 disk format (was bf16/f64 dual-version).
  - Deleted --bf16 CLI flag from precompute_features
  - PVC cache files need regeneration via precompute_features

TF32 tensor cores activated via cublasLtMatmul CUBLAS_COMPUTE_32F — no
explicit TF32 types needed. Storage is pure f32 everywhere.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 18:52:21 +02:00
jgrusewski
00bbe76b05 refactor: fxcache single f32 format — delete bf16 version, remove --bf16 CLI flag
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 18:45:49 +02:00
jgrusewski
d11b9870ff refactor: gpu_dqn_trainer — rename all bf16 fields/variables to f32, fix cast kernel names
- Rename f32_to_bf16_kernel → copy_kernel_a, bf16_to_f32_kernel → copy_kernel_b
- Rename bf16_states_buf → states_staging_buf, bf16_next_states_buf → next_states_staging_buf
- Convert staging buffers from CudaSlice<u16>/alloc_u16 → CudaSlice<f32>/alloc_f32
- Fix bias_bf16 → bias_f32 (remove redundant identity map)
- Rename launch_f32_to_bf16_params_cast → launch_f32_copy_params
- Rename launch_f32_to_bf16_target_cast → launch_f32_copy_target
- Rename cast_d_logits_to_bf16 → cast_d_logits_to_f32_staging
- Rename check_nan_bf16 → check_nan_f32_b, fix duplicate nan_check_f32_kernel field
- Fix dtod_from_bf16 → dtod_from_staging (now CudaSlice<f32>)
- Fix launch_bf16_to_f32 → launch_f32_copy (now f32→f32)
- Update all ~90 bf16 comments/error messages to f32
- Only remaining bf16 refs are CUDA kernel name strings (must match .cu source)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 18:28:06 +02:00
jgrusewski
0131b2904b refactor: rename all bf16 transfer functions → f32 across 19 files, delete legacy aliases
htod_f32_to_bf16 → htod_f32, clone_htod_f32_to_bf16 → clone_htod_f32,
dtoh_bf16_to_f32 → dtoh_f32. No wrappers — all 67 call sites renamed directly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 18:11:50 +02:00
jgrusewski
95edfd024b refactor: gpu_weights all CudaSlice<half::bf16> → CudaSlice<f32>, delete bf16 mirror infrastructure
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 18:11:09 +02:00
jgrusewski
8fa301dda8 refactor: mod.rs bf16 helpers → direct f32 transfers, legacy aliases for incremental migration
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 18:06:25 +02:00
jgrusewski
eb2c16acb9 refactor: eliminate __nv_bfloat16 from all 30 CUDA kernel files and shared header
Mechanical regex sweep: __nv_bfloat16 → float, __float2bfloat16(x) → (x),
__bfloat162float(x) → (x), removed cuda_bf16.h includes. Conversion kernels
(f32_to_bf16_kernel, bf16_to_f32_kernel) are now identity copies. Removed
duplicate overloads (matvec_leaky_relu, curiosity_inference) that became
identical after type substitution.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 18:01:59 +02:00
jgrusewski
0662f9bbf8 refactor: rewrite common_device_functions.cuh — bf16 wrappers now pure f32 identity functions
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 17:58:22 +02:00
jgrusewski
0fa5b993dd fix(proper): force cuMemAlloc_v2 in cudarc — cuMemAllocAsync incompatible with cublasLtMatmul on H100
Root cause: cuMemAllocAsync (stream-ordered memory pools) produces
memory that cublasLtMatmul rejects with CUBLAS_STATUS_NOT_SUPPORTED
on H100 (CUDA 13.0 driver) when the matmul runs on a different
stream than the allocation. Despite CUDA documentation stating
same-device async allocations should be accessible from all streams
with proper event synchronization, cublasLtMatmul disagrees.

Proof chain:
- C++ test with cudaMalloc: ALL dimensions pass on H100 ✓
- Rust test with cuMemAlloc: ALL dimensions pass on H100 ✓
- Rust test with cudarc alloc_zeros (cuMemAllocAsync): FAILS ✗
- Same dimensions, same handle, same workspace — only alloc differs

Fix: set has_async_alloc=false unconditionally in CudaContext::new().
This forces cuMemAlloc_v2 for ALL allocations. Zero performance impact
(allocations at construction time, not in hot loops).

Also: converted has_async_alloc from bool to AtomicBool for safety.
Removed diagnostic code (CUBLASLT_DIAG, test_lt_matmul_raw).
Reverted cuMemAlloc workspace hack (now uses normal alloc_zeros).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 17:33:50 +02:00
jgrusewski
5a72d6e00b fix(critical): disable cuMemAllocAsync — use cuMemAlloc for cublasLtMatmul compat
Root cause: cudarc uses cuMemAllocAsync (stream-ordered memory pools)
on H100 where CU_DEVICE_ATTRIBUTE_MEMORY_POOLS_SUPPORTED=1. These
allocations are only accessible from the allocating stream.
cublasLtMatmul dispatches GEMM work on branch streams (multi-stream
fork-join for parallel advantage heads), which can't access
stream-local memory from the main stream — returns NOT_SUPPORTED.

Proof: C++ test with cudaMalloc passes ALL dims on H100 ✓
       Rust test_lt_matmul_raw with cuMemAlloc passes on H100 ✓
       Same Rust code with cudarc alloc_zeros (cuMemAllocAsync) FAILS ✗

Fix: add CudaContext::disable_async_alloc() to vendored cudarc.
Called in DQN::new_with_stream() to force cuMemAlloc_v2 for ALL
allocations. No performance impact (allocations at construction,
not in hot loops).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 15:42:04 +02:00
jgrusewski
8b9d8e0988 diag: test cublasLtMatmul with fresh cudaMalloc buffers before experience collector forward
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 14:29:01 +02:00