Gate virtual-bullet spawn on rack admission: +68% tick rate, selected gun unchanged
The default rack is now Pattern-only (31c7c01), but membership filters SELECTION,
not SPAWNING - so all 13 unselected guns still ran `predict` + `spawnBullets`
every tick to feed fitness tables nobody reads. Measured waste: Tsetlin alone
0.98 ms/tick, KNN 0.30, plus 10 more. This generalises the gate TMPATTERN already
had to every gun, behind `TR_VBULLET_ADMIT_ONLY` (default 1 = gate, 0 = old).
OFFLINE COST (release build, 400 ticks, min of 2 reps, 13-gun rack):
OFF 2.14 ms/tick (implied 467 ticks/s)
ON 0.04 ms/tick (implied 27667 ticks/s)
-> reclaimed 2.10 ms/tick, ~98% of the virtual-bullet cost. Tsetlin's 0.98
disappears, KNN's 0.30 disappears, only Pattern (0.017) survives.
Note the absolute scale is lower than an earlier unoptimised measurement (~6.1
ms/t) because this is a -d:release build; the ON-vs-OFF DELTA is the robust result.
LIVE TICK RATE (ONE frozen binary, 4 runs/arm x 4 rounds, all 8 concurrent, gate
varied by env only):
ON 146.2 ticks/s (142.3, 145.2, 147.9, 149.4)
OFF 86.9 ticks/s ( 95.0, 41.4, 99.1, 112.1)
NO OVERLAP: ON min 142.3 > OFF max 112.1. Excluding a game-outcome outlier in
the OFF arm, OFF max is still 112.1. Outside the noise.
**+68% tick rate**, which also makes every future A/B faster. Both arms still pay
the fixed 8192-slot ring scan in tickBullets.
SAFETY, verified not assumed: Pattern is admitted under the shipped rack, so its
own fitness keeps accumulating and the SELECTED gun is unchanged - Pattern 100% in
all 4 runs both arms, and Pattern was the ONLY gun with vShots>0 in the ON arm
while all 13 had vShots>0 in the OFF arm. So admission is the correct predicate.
Mid-round transitions are safe by construction: only predict/spawn are gated, while
tickBullets still resolves every active bullet and the feedback case still calls
the owning gun's onResult.
A TOOLING BUG THIS CAUGHT, and a correction to the task's assumption:
`acceptance_offline_vs_online.nim` IS affected (I had assumed it was not). It
compares the live per-gun vShots against an offline replay that always spawns all
guns, so under the default gate the online non-Pattern vShots are 0 while offline
is ~400 - a guaranteed mismatch. Fixed by pinning `TR_VBULLET_ADMIT_ONLY=0` inside
that test (same putEnv/defer pattern as TR_RECORD_WORLDSTATE), keeping 12/12. The
test is about offline/online METRIC parity, so it needs every gun spawning.
Unaffected (verified from source): audit_virtual_guns.nim,
measure_cornering_guns.nim, sweep_tm_pattern.nim - all offline, none read
GUN_STATS_PATH.
Guards: test_vbullet_admit_gate 12 (new, pure), test_gun_harness 39,
test_vbullet_metric 11, test_power_selection 3, test_adaptive_radar 41,
test_tfil_ring_weights 24, test_power_policy 26, test_ram_decision 28,
test_rack_membership 48, test_selector_tiebreak 19, test_tm_pattern_registration 20,
test_tm_pattern_learning 3, acceptance_offline_vs_online 12/12. ModularBot compiles.
This commit is contained in:
@@ -230,6 +230,24 @@ proc admittedGuns*(fitLen: int, mode: RackMode,
|
||||
if result.len == 0:
|
||||
for gunId in 0..<fitLen: result.add gunId
|
||||
|
||||
proc vBulletAdmitted*(gunId: int, mode: RackMode,
|
||||
membership: openArray[RackMembership],
|
||||
admitOnly: bool = true): bool =
|
||||
## `TR_VBULLET_ADMIT_ONLY` gate for the LIVE predict+spawn block.
|
||||
##
|
||||
## Rack membership historically filtered only SELECTION, so every unselected
|
||||
## gun still ran `predict`/`spawnBullets` each tick to feed a fitness table the
|
||||
## selector would never read. This predicate lets the live loop skip BOTH for a
|
||||
## gun the current rack does not admit.
|
||||
##
|
||||
## admitOnly = true (SHIPPED default) — a gun spawns only while admitted.
|
||||
## admitOnly = false — every gun spawns (the pre-change behaviour).
|
||||
##
|
||||
## `onResult` feedback is deliberately NOT covered here: a bullet spawned
|
||||
## while admitted must still resolve and be attributed to its gun even if the
|
||||
## rack changes mid-round.
|
||||
(not admitOnly) or rackAdmitted(gunId, mode, membership)
|
||||
|
||||
# ── runtime ranking knobs (A/B without rebuilding) ────────────────────────────
|
||||
#
|
||||
# Every knob below defaults to the SHIPPED constant, so an unset environment
|
||||
|
||||
Reference in New Issue
Block a user