…t not in the docs (#1347)
The knob shipped with fork #216 and the pin now carries it (engine main c752b66 pins llama.cpp 092eb9dbc, and
469c69f5d is an ancestor), but docs/hrx.md never mentioned it. Rule: docs travel with the behaviour they describe.
What it says: Flash-Next's 48 MoE blocks are a quant mix (UD-IQ4_XS keeps IQ3_XXS on 28 of them), IQ3_XXS blocks cost
~2.4x the IQ4_XS blocks on identical geometry, and the knob selects a second router-expert kernel that decodes the
IQ3_XXS grid from a per-workgroup table. Off by default; unset or 0 is the shipping path.
Measured, one hold, control arm on the same binary: pp4096 270.62 -> 318.52 (1.18x) and 140.84 -> 182.10 (1.29x) in a
second window, pp512 177.62 -> 221.38 (1.25x), PPL 8x512 1.7198 -> 1.7198 identical (and identical in three separate
windows). The absolute tok/s carry their own warning: the same arm has read 182-318 tok/s across windows for identical
flags, so only paired ratios are quoted.
Why it stays opt-in, written into the section rather than left implicit: those two windows ran on a fork commit that
predates #227, and a 3,858-token prompt on it intermittently died in the CPU fallback of SET_ROWS (engine #1251). A
default change needs the long-prompt cell and test-backend-ops -o MUL_MAT -b HRX0 on the current pin; neither has been
run by this lane.
Part of #572.
Co-authored-by: bong-water-water-bong <bong-water-water-bong@1bit.gg>
This opens the Laya router to the NPU (geramyl: "HRX + LOOM + NPU"). The engine gets only a generic hook. The NPU code stays in the private add-on.
Engine side (public):
laya/encoder.h: a registry of encoders by name. An encoder gets a sequence's embedded rows[rows][1024]withnreal tokens, runs the 28 layers in place, and may decline.Scorer::set_encoder:score()hands every sequence to the set encoder. If the encoder declines any of them, the whole batch runs on the CPU as before.serve --layawithONEBIT_LAYA_DEVICE=npuuses the C++ scorer with thenpuencoder instead of the GGUF daemon. It fails before loading the checkpoint, saying how to build, when no add-on registered one.tests/laya_encoder_test.cpp(ctestlaya_encoder) covers the registry.tests/laya_gguf_route.shchecks the missing-add-on message.docs/laya.md("The encoder on the NPU") anddocs/npu.md.Private side, for reference: npu-kernels
addons/npu-layaregistersnpu. It takes the engine's NPU device lock without waiting, and declines while another process holds it, so those decisions run on the CPU. It keeps its hardware context together with the lock for 2 s after a call, then releases both.Measured on strixhalo (
serve --layawith fake backends andtests/route-policy-e2e.json, real checkpoint):Local ctest passes 13/13.
🤖 Generated with Claude Code