feat(dqn-v2): Plan 4 Task 1A — feature-group index ranges for VSN/attention consumers
Adds 12 new `SL_*_GROUP_BEGIN/END` macros to `state_layout.cuh` covering the 6 feature groups (market/ofi/tlob/mtf/portfolio/plan_isv), plus `SL_NUM_FEATURE_GROUPS=6` and `SL_MAX_FEATURE_GROUP_DIM=42` (= largest group dim, MARKET_DIM). Six new `static_assert`s anchor each group dim ≤ max and confirm contiguity / start-at-zero / end-at-padding invariants. Rust mirror in `crates/ml-core/src/state_layout.rs` exposes: - `SL_NUM_FEATURE_GROUPS` - `SL_MAX_FEATURE_GROUP_DIM` - `FEATURE_GROUP_RANGES: [(usize, usize); 6]` (half-open `[begin, end)`, `plan_isv` ends at `PADDING_START` — padding is not a group) - `FEATURE_GROUP_NAMES: [&str; 6]` Three `const _: () = assert!(...)` blocks validate (1) first range starts at 0, (2) last range ends at `PADDING_START`, (3) every adjacent pair satisfies `ranges[g].end == ranges[g+1].begin` (no gaps), (4) every group dim ≤ `SL_MAX_FEATURE_GROUP_DIM`. Group dims at this commit: market=42, ofi=32, tlob=16, mtf=16, portfolio=8, plan_isv=7 — total 121 = `PADDING_START`. Prerequisite for Plan 4 Task 1B (E.1 Variable Selection Network — pre-trunk per-group softmax-over-groups gating), Task 5 Mode B (per-group ISV diagnostics), and Task 4 follow-on (group-aware encoder interface). Additive only — ZERO production callers in this commit. No new module / kernel / ISV slot / param tensor / Orphan row. No fingerprint change (group ranges are derivable from existing `SL_*_START` constants and contribute no new structural-hash invariant). cargo check clean at 11 warnings (workspace baseline preserved); cargo build compiles all kernel cubins (state_layout.cuh edit triggers full kernel rebuild — no compile errors). Audit doc: 1 new entry under "Plan 4 Task 1A". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -162,3 +162,83 @@ pub const MAG_QUARTER: usize = 0; // 0.25× max_position
|
||||
pub const MAG_HALF: usize = 1; // 0.50× max_position
|
||||
pub const MAG_FULL: usize = 2; // 1.00× max_position
|
||||
pub const NUM_MAGNITUDES: usize = 3;
|
||||
|
||||
// ────────────────────────────────────────────────────────────────────────────
|
||||
// Feature-group ranges — Plan 4 Task 1A (E.1 VSN prerequisite).
|
||||
//
|
||||
// Mirrors the `SL_*_GROUP_BEGIN/END` macros in
|
||||
// `crates/ml/src/cuda_pipeline/state_layout.cuh`. Ranges are half-open
|
||||
// `[begin, end)`. The last group (`plan_isv`) ends at `PADDING_START` —
|
||||
// the 7-element zero-pad block is *not* a feature group.
|
||||
//
|
||||
// Consumers:
|
||||
// * Plan 4 Task 1 (E.1) Variable Selection Network — gates each group's
|
||||
// features by a learned softmax-over-groups mask before the trunk.
|
||||
// * Plan 4 Task 5 (E.5) attention-weight ISV diagnostics.
|
||||
// * Plan 4 Task 4 (E.4) encoder-decoder separation — group-aware
|
||||
// `StateEncoder` interface.
|
||||
// ────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
pub const SL_NUM_FEATURE_GROUPS: usize = 6;
|
||||
|
||||
/// Largest per-group dimension (currently `MARKET_DIM = 42`). Used for kernel-
|
||||
/// side fixed-size scratch arrays so every group fits a uniform stride.
|
||||
pub const SL_MAX_FEATURE_GROUP_DIM: usize = MARKET_DIM;
|
||||
|
||||
/// `[begin, end)` ranges per feature group, in declaration order.
|
||||
/// Order matches `FEATURE_GROUP_NAMES`.
|
||||
pub const FEATURE_GROUP_RANGES: [(usize, usize); SL_NUM_FEATURE_GROUPS] = [
|
||||
(MARKET_START, OFI_START), // [0] market — 42 dims
|
||||
(OFI_START, TLOB_START), // [1] ofi — 32 dims
|
||||
(TLOB_START, MTF_START), // [2] tlob — 16 dims
|
||||
(MTF_START, PORTFOLIO_START), // [3] mtf — 16 dims
|
||||
(PORTFOLIO_START, PLAN_ISV_START), // [4] portfolio — 8 dims
|
||||
(PLAN_ISV_START, PADDING_START), // [5] plan_isv — 7 dims
|
||||
];
|
||||
|
||||
/// Group names — index-aligned with `FEATURE_GROUP_RANGES`. Used for ISV
|
||||
/// diagnostic labels (`VSN_MASK_GROUP_<NAME>_EMA`) and audit-doc rows.
|
||||
pub const FEATURE_GROUP_NAMES: [&str; SL_NUM_FEATURE_GROUPS] = [
|
||||
"market",
|
||||
"ofi",
|
||||
"tlob",
|
||||
"mtf",
|
||||
"portfolio",
|
||||
"plan_isv",
|
||||
];
|
||||
|
||||
// ── Compile-time invariants ───────────────────────────────────────────────
|
||||
const _: () = assert!(
|
||||
FEATURE_GROUP_RANGES[0].0 == 0,
|
||||
"feature groups must start at offset 0"
|
||||
);
|
||||
const _: () = assert!(
|
||||
FEATURE_GROUP_RANGES[SL_NUM_FEATURE_GROUPS - 1].1 == PADDING_START,
|
||||
"feature groups must end at PADDING_START — padding is not a group"
|
||||
);
|
||||
const _: () = {
|
||||
// Every adjacent pair (g, g+1) must satisfy ranges[g].end == ranges[g+1].begin
|
||||
// so the groups contiguously cover [0, PADDING_START) with no gaps.
|
||||
let mut g = 0;
|
||||
while g + 1 < SL_NUM_FEATURE_GROUPS {
|
||||
assert!(
|
||||
FEATURE_GROUP_RANGES[g].1 == FEATURE_GROUP_RANGES[g + 1].0,
|
||||
"feature group ranges must be contiguous (no gaps)"
|
||||
);
|
||||
g += 1;
|
||||
}
|
||||
};
|
||||
const _: () = {
|
||||
// Each group's dim must fit within SL_MAX_FEATURE_GROUP_DIM so kernel
|
||||
// scratch arrays sized to the maximum can hold any group.
|
||||
let mut g = 0;
|
||||
while g < SL_NUM_FEATURE_GROUPS {
|
||||
let (b, e) = FEATURE_GROUP_RANGES[g];
|
||||
assert!(e >= b, "feature group end must not precede begin");
|
||||
assert!(
|
||||
e - b <= SL_MAX_FEATURE_GROUP_DIM,
|
||||
"feature group dim must not exceed SL_MAX_FEATURE_GROUP_DIM"
|
||||
);
|
||||
g += 1;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -151,6 +151,31 @@
|
||||
#define ISV_SEED_STEPS_DONE_IDX 83 // == SEED_STEPS_DONE_INDEX — cumulative seed-phase steps completed (Plan 3 Task 8 B.3)
|
||||
#define ISV_SEED_FRAC_EMA_IDX 84 // == SEED_FRAC_EMA_INDEX — adaptive EMA of (1 - done/target) ∈ [0, 1] (Plan 3 Task 8 B.3; consumed by Task 9 CQL ramp)
|
||||
|
||||
// ────────────────────────────────────────────────────────────────────────────
|
||||
// Feature-group ranges — Plan 4 Task 1A (E.1 VSN prerequisite).
|
||||
// Referenced by: VSN feature selection (E.1), attention diagnostics (E.5),
|
||||
// encoder-decoder separation (E.4). Ranges are half-open `[BEGIN, END)`.
|
||||
// `SL_PLAN_ISV_GROUP_END` aliases `SL_PADDING_START` because the 7-element
|
||||
// plan-ISV block is the last group before the 8-alignment padding.
|
||||
// Invariant 8: every range has a named constant; raw `SL_*_START` arithmetic
|
||||
// for group bounds outside this header is a lint violation.
|
||||
// ────────────────────────────────────────────────────────────────────────────
|
||||
#define SL_MARKET_GROUP_BEGIN SL_MARKET_START
|
||||
#define SL_MARKET_GROUP_END SL_OFI_START
|
||||
#define SL_OFI_GROUP_BEGIN SL_OFI_START
|
||||
#define SL_OFI_GROUP_END SL_TLOB_START
|
||||
#define SL_TLOB_GROUP_BEGIN SL_TLOB_START
|
||||
#define SL_TLOB_GROUP_END SL_MTF_START
|
||||
#define SL_MTF_GROUP_BEGIN SL_MTF_START
|
||||
#define SL_MTF_GROUP_END SL_PORTFOLIO_START
|
||||
#define SL_PORTFOLIO_GROUP_BEGIN SL_PORTFOLIO_START
|
||||
#define SL_PORTFOLIO_GROUP_END SL_PLAN_ISV_START
|
||||
#define SL_PLAN_ISV_GROUP_BEGIN SL_PLAN_ISV_START
|
||||
#define SL_PLAN_ISV_GROUP_END SL_PADDING_START
|
||||
|
||||
#define SL_NUM_FEATURE_GROUPS 6
|
||||
#define SL_MAX_FEATURE_GROUP_DIM 42 // == SL_MARKET_DIM (largest group)
|
||||
|
||||
// ── Compile-time checks ──
|
||||
static_assert(SL_PADDING_START + SL_PADDING_DIM == SL_STATE_DIM,
|
||||
"State layout dimensions must sum to SL_STATE_DIM");
|
||||
@@ -158,6 +183,23 @@ static_assert(SL_STATE_DIM % 8 == 0,
|
||||
"SL_STATE_DIM must be 8-aligned for tensor core cuBLAS");
|
||||
static_assert(SL_STATE_DIM <= SL_STATE_DIM_PADDED,
|
||||
"SL_STATE_DIM must fit within SL_STATE_DIM_PADDED");
|
||||
// Feature groups must contiguously cover the non-padding state range.
|
||||
static_assert(SL_MARKET_GROUP_BEGIN == 0,
|
||||
"feature groups must start at offset 0");
|
||||
static_assert(SL_PLAN_ISV_GROUP_END == SL_PADDING_START,
|
||||
"feature groups must end at SL_PADDING_START — padding is not a group");
|
||||
static_assert(SL_MARKET_DIM <= SL_MAX_FEATURE_GROUP_DIM,
|
||||
"Market group dim must not exceed SL_MAX_FEATURE_GROUP_DIM");
|
||||
static_assert(SL_OFI_DIM <= SL_MAX_FEATURE_GROUP_DIM,
|
||||
"OFI group dim must not exceed SL_MAX_FEATURE_GROUP_DIM");
|
||||
static_assert(SL_TLOB_DIM <= SL_MAX_FEATURE_GROUP_DIM,
|
||||
"TLOB group dim must not exceed SL_MAX_FEATURE_GROUP_DIM");
|
||||
static_assert(SL_MTF_DIM <= SL_MAX_FEATURE_GROUP_DIM,
|
||||
"MTF group dim must not exceed SL_MAX_FEATURE_GROUP_DIM");
|
||||
static_assert(SL_PORTFOLIO_BASE_DIM <= SL_MAX_FEATURE_GROUP_DIM,
|
||||
"Portfolio group dim must not exceed SL_MAX_FEATURE_GROUP_DIM");
|
||||
static_assert(SL_PORTFOLIO_PLAN_DIM <= SL_MAX_FEATURE_GROUP_DIM,
|
||||
"Plan-ISV group dim must not exceed SL_MAX_FEATURE_GROUP_DIM");
|
||||
|
||||
// ── Shared state assembly function ──
|
||||
// Called by both experience_state_gather (training) and backtest_state_gather (validation).
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user