Two CUDA Graph prerequisites implemented:
1. Device-resident step counter (ISV[548]):
- New rl_increment_step.cu kernel (single thread, ISV += 1)
- All kernels that took current_step as scalar now read from ISV
- Updated: confidence_gate, frd_gate, unit_state_update,
trade_context_update, gate_threshold_controller
- Enables CUDA Graph capture (no scalar arg changes between replays)
2. Fused controllers (rl_fused_controllers.cu):
- Combines 10 single-thread controllers into 1 kernel launch:
gamma, tau, ppo_clip, entropy, rollout_steps, per_alpha,
reward_scale (with ±2% clamp), ppo_ratio_clamp,
gate_threshold, q_distill_lambda
- Saves 9 kernel launches per step (~40-80μs)
- Individual .cu files retained for testing/documentation
ISV slot 548 (step counter). Local smoke: 100 steps, no crash.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
21 lines
823 B
Plaintext
21 lines
823 B
Plaintext
// rl_increment_step.cu — bump the device-resident step counter.
|
|
//
|
|
// Single thread (grid=1, block=1), runs once per step at the very start
|
|
// of the step_with_lobsim pipeline, BEFORE any kernel that reads
|
|
// current_step. Kernels read `(int)isv[RL_STEP_COUNTER_ISV_INDEX]`
|
|
// instead of receiving `int current_step` as a scalar argument. This
|
|
// makes ALL kernel argument lists constant across calls, enabling CUDA
|
|
// Graph capture (scalar args can't change between replays).
|
|
//
|
|
// Per `feedback_no_atomicadd`: single thread, no atomics.
|
|
// Per `feedback_cpu_is_read_only`: pure device-side increment.
|
|
|
|
#define RL_STEP_COUNTER_ISV_INDEX 548
|
|
|
|
extern "C" __global__ void rl_increment_step(
|
|
float* __restrict__ isv
|
|
) {
|
|
if (threadIdx.x != 0 || blockIdx.x != 0) return;
|
|
isv[RL_STEP_COUNTER_ISV_INDEX] += 1.0f;
|
|
}
|