Debug switches¶
Debug switches are environment variables that change how gmlx builds or routes a model, or make it report what it did, so that an A/B run can isolate a defect. The user-facing variables are in Environment variables.
The disabling switches slow the model or turn a fix off. Most logging switches cost nothing but output, but the layer profile evaluates after each layer part and slows the run it measures. A switch that takes a number moves a threshold or a width, so that a run can test a component at more than one setting. The module that reads a switch holds its default.
Contents¶
Speculative decoding¶
| Variable | Meaning |
|---|---|
GMLX_DSPARK_CONF=T |
Set a DSpark drafter's block-cut confidence threshold, in 0..1. |
GMLX_SPEC_GATE=X |
Run a greedy DFlash 2 round expected to emit fewer than X tokens as one plain step, with the same output. auto derives X from round costs. |
GMLX_QWEN_OWNED=0 |
Build Qwen3.5 and 3.6 text MTP targets on stock mlx-vlm classes, without the gmlx performance patches and fixes. |
GMLX_GEMMA_OWNED=0 |
Build gemma-4 text MTP targets on stock mlx-vlm classes. Numerics are unchanged. |
GMLX_GDN_REPLAY=0 |
Store the recurrent state after each verify position instead of records that the next step replays. Output is bit-identical. |
GMLX_MTP_DEBUG=1 |
Log the MTP notices, including the verify branch the first time each branch runs. |
Prompt cache¶
The switches for each prompt cache layer are read in gmlx/spec/engine.py
and gmlx/cache/, and
Prompt cache internals describes the
layers.
| Variable | Meaning |
|---|---|
GMLX_SPEC_APC=0 |
Turn every speculative cache layer off at once, including lookups, stores, the sidecar and the checkpoint tier. |
GMLX_SPEC_APC_RETIRE=0 |
Turn off only the retirement store. |
GMLX_SPEC_APC_SIDECAR=0 |
Turn off only the drafter-KV sidecar. |
GMLX_SPEC_APC_CKPT=0 |
Turn off only the checkpoint tier, so the exact full-clone path serves those models. |
GMLX_SPEC_APC_ENTRIES |
Keep this many entries in the prefix layer. |
GMLX_SPEC_APC_SIDECAR_ENTRIES |
Keep this many entries in the drafter sidecar. |
GMLX_SPEC_APC_BUDGET_MB |
Keep the prefix layer within this many MB. |
GMLX_SPEC_APC_SIDECAR_BUDGET_MB |
Keep the drafter sidecar within this many MB. |
GMLX_APC_STORE_EVAL_CHUNK |
Evaluate this many blocks per step in the post-prefill store, which bounds the stall on a long prompt. |
GMLX_APC_CKPT_INTERVAL |
Space prefill checkpoints this many tokens apart. 0 saves only the final checkpoint. |
GMLX_APC_CKPT_REPLAY=0 |
Disable the replay checkpoint, so an identical resend prefills cold again. |
GMLX_APC_CKPT_REPLAY_MIN |
Take a replay checkpoint on a recurrent model only for a prompt of at least this many tokens. |
GMLX_APC_CKPT_TURN=0 |
Disable the turn checkpoint, so next-turn reuse falls back to the interval grid. |
GMLX_APC_CKPT_SYS=0 |
Disable the system-prompt anchor on both tiers. |
GMLX_APC_CKPT_SYS_MIN |
Anchor a system prompt only past this many tokens of shared prefix. |
GMLX_APC_ANCHOR_ENTRIES |
Keep this many system-prompt anchors on an exact-tier model. |
GMLX_APC_ANCHOR_BUDGET_MB |
Keep the exact-tier anchors within this many MB. The newest anchor is never evicted. |
GMLX_APC_CKPT_TRIPWIRE |
Warn about a model that stores nothing, or that matches but adopts nothing, after this many requests. 0 silences both warnings. |
GMLX_APC_CKPT_RECORDS |
Keep this many checkpoint records. |
GMLX_APC_CKPT_BUDGET_MB |
Keep the checkpoint payload within this many MB. |
GMLX_APC_DECODE_CKPT |
Snapshot a checkpoint-tier model at this interval in generated tokens. 0 turns it off. |
GMLX_APC_RETIRE_LCP=0 |
Key retirement on the forwarded ids instead of the predicted next-turn render. This also disables decode-time snapshots. |
GMLX_APC_FRESH_WAIT_MS |
Admit siblings that arrive together one at a time, holding each at most this many ms. 0 disables the gate. |
GMLX_APC_FRESH_MIN |
Hold a sibling only past this many uncovered shared-prefix tokens. |
Attention and KV cache¶
These switches change how attention runs or how the KV cache is stored, or log the attention route.
| Variable | Meaning |
|---|---|
GMLX_KVARN=0 |
Disable --kv-quant-scheme kvarn at cache build, so the model runs fp16 KV. |
GMLX_KVARN_SDPA=0 |
Route kvarn decode through the materialize path instead of the fused record kernels. Output differs at fp16 rounding only. |
GMLX_KVARN_FA=0 |
Keep kvarn MTP verify on the vector kernel instead of the matrix-unit kernel. Numerics match to fp16 rounding. |
GMLX_ROPE_FACTORS=0 |
Disable the patch that rebuilds Llama-3.1-style per-dimension rope scaling from GGUF metadata. |
GMLX_SPARSE_ARCHS |
Name extra architecture modules for the sparse attention route, comma separated, to quality-gate a new architecture. |
GMLX_SDPA_DEBUG=1 |
Log the attention route of the first long calls, so a wrong route on a new architecture shows in the log. |
GMLX_ROUTE_LOG=1 |
Print per-route attention call counts at process exit. |
Model kernels¶
These switches turn off, resize or trace individual model kernels and fusions.
| Variable | Meaning |
|---|---|
GMLX_FUSED_GDN=0 |
Disable the fused gated-delta Metal kernels of the Qwen3.5 and 3.6 hybrids. The fusion affects numerics. |
GMLX_HADAMARD_KERNEL=0 |
Run the Hadamard-fold rotation as MLX ops instead of the mlx-kquant kernel. Numerics match to one rounding. |
GMLX_HADAMARD_FUSE=0 |
Rotate the input of a folded down or output projection in its own dispatch instead of inside the gate kernel. |
GMLX_HADAMARD_TRACE=1 |
Count the rotations on a folded file since the last hadamard_modules.reset_rotation_count call, read back through hadamard_modules.rotation_count. |
GMLX_HADAMARD_ROTATE=0 |
Skip the Hadamard-fold rotation. The model produces garbage, and a benchmark measures the whole cost of the rotation. |
GMLX_MOE_GATEUP_CONCAT=0 |
Disable the prefill gate and up expert concat, which trades a second resident copy of the wire bytes for one gather. |
GMLX_MOE_GATEUP_CONCAT_MAX_MB |
Cap the concat copies at this many MB, stamping layers in order until the cap is reached. |
GMLX_MOE_GATEUP_CONCAT_HEADROOM_GB |
Skip a concat copy that would leave less than this many GB under the memory ceiling. 0 turns the check off. |
GMLX_MOE_MIX_PREFILL=0 |
Keep the eager unsort and score mix after the sorted-prefill down gather instead of one gather_mix dispatch. |
GMLX_GLM5_ABSORBED_MAX_L |
Run GLM-5.3-Flash MLA layers in the absorbed MQA form up to this many queries. 0 expands the latent per head everywhere. |
GMLX_GLM5_INDEXER_DECODE=0 |
Score the GLM-5.3-Flash indexer inline instead of through the fused scorer and radix top-k. |
GMLX_GLM5_SPARSE_INDEXED=0 |
Disable index-gathered attention for GLM-5.3-Flash sparse decode and verify. |
GMLX_GLM5_KDA_FUSED_MAX_T |
Run GLM-5.3-Flash KDA steps up to this width as one fused decode dispatch. 0 restores the op chain everywhere. |
GMLX_GLM5_KDA_CHUNK=0 |
Keep GLM-5.3-Flash KDA prefill on the token-sequential kernel instead of the chunked recurrence. |
GMLX_GLM5_KDA_CONV=0 |
Keep the eager GLM-5.3-Flash KDA prefill chain instead of the mlx-kquant glue kernels. |
GMLX_HC_M1_MAX_ROWS |
Run hyper-connected steps up to this many rows on the fused per-row kernels. Wider steps take the GEMM route. |
GMLX_HC_M1_FUSED=0 |
Disable the fused per-row hyper-connection kernels, leaving every step on the GEMM route. |
GMLX_HC_FUSED_CYCLE=0 |
Restore the two-kernel hyper-connection cycle instead of one mlx-kquant dispatch. Output is bit-identical. |
GMLX_DS41_HC_FUSED=0 |
Run DeepSeek-V4.1 hyper-connection cycles op by op instead of on the fused kernels. |
GMLX_DS41_QAT_FUSED=0 |
Run DeepSeek-V4.1 quantization round trips as compiled op chains instead of one kernel each. Output is bit-identical. |
GMLX_DS41_SPARSE_KERNEL=0 |
Run DeepSeek-V4.1 decode attention as a gather and op chain instead of sdpa_sparse_decode. |
GMLX_DS41_SPARSE_KERNEL_BLOCK=N |
Set the queries per sdpa_sparse_decode call in a DeepSeek-V4.1 prefill. 0 keeps prefill blocks on the op chain. |
GMLX_DS41_SPARSE_PREFILL=0 |
Run DeepSeek-V4.1 prefill attention as sdpa_sparse_decode query blocks instead of one sdpa_sparse_prefill call per layer. |
GMLX_DS41_INDEXER_DECODE=0 |
Compute DeepSeek-V4.1 decode indexer scores on the inline op chain instead of the fused kernel. |
GMLX_DS41_POOL_FP4=0 |
Keep the DeepSeek-V4.1 latent pool as fp16 rows instead of FP4 codes. Output is bit-identical. |
GMLX_DS41_INDEXER_CAND=0 |
Score every pooled row under a mask in the later DeepSeek-V4.1 indexer layers instead of only the candidate rows. |
GMLX_DS41_PREFILL_STEP=N |
Prefill DeepSeek-V4.1 in N-token chunks. 0 restores the generic default. |
GMLX_DS41_PREFILL_TAIL=0 |
Run every DeepSeek-V4.1 layer on every prompt row instead of skipping rows no later window reaches. |
GMLX_DS4_PREFILL_BLOCK=N |
Set the DeepSeek-V4.1 prefill query-block width for the window, sparse and indexer scores. 0 scores the whole chunk. |
GMLX_DSA_INDEXER=0 |
Compute DeepSeek-V4 and V4.1 indexer scores and top-k on the inline fp32 op chain instead of the mlx-kquant kernels. |
GMLX_DSA_INDEXER_Q=0 |
Keep the indexer GEMM on fp16 operands where tensor-op hardware would run the int8 kernel. Output is bit-identical. |
GMLX_CB_PHASE=0 |
Disable the per-phase MLX command-buffer caps. Output is unchanged, and decode runs slower. |
Streaming¶
| Variable | Meaning |
|---|---|
GMLX_DECODE_LOOKAHEAD_PROBE=1 |
Record predicted against actual expert routing per layer and print the recall table at exit, issuing no reads. |
GMLX_PIN_CAST_EXCLUDE=0 |
Pin the file bytes of every every-token tensor, including the tensors the loader converts at load. |
GMLX_STREAM_PLE_COMPOSE=0 |
Keep a streamable lookup table resident when the experts also stream. |
GMLX_RELEASE_PAGECACHE=0 |
Keep a released over-RAM model's pages in the page cache at exit or unload. |
Training¶
| Variable | Meaning |
|---|---|
GMLX_TRAIN_BLOCKED_ATTN=0 |
Run training attention on the unfused MLX path instead of the query-block recompute in gmlx.tune.attention. |
GMLX_TRAIN_GDN_CHUNK=0 |
Run a training forward's gated delta scan on mlx-lm's per-token loop instead of the chunked rule in gmlx.tune.gdn. |
MLX_ENABLE_TF32=1 |
Keep TF32 float32 matmul in gmlx train and gmlx distill, which otherwise turn it off. The chunked gated delta rule then takes the loop. |
Profiling¶
These switches time a run's parts and print or write the results.
| Variable | Meaning |
|---|---|
GMLX_ROUND_PROFILE=1 |
Profile each speculative round, in the server process too. GMLX_ROUND_LOG=/path.tsv writes the rounds to a TSV file. |
GMLX_DECODE_PHASE_STATS=1 |
Print the per-token split of a streamed decode between disk stalls and the eval and sync bucket at exit. A clock drop shows as a large sync bucket. |
GMLX_DECODE_PHASE_LAYERS=1 |
With the phase stats, also print the split per layer and each token's arena misses. |
GMLX_DECODE_LAYER_PROFILE=1 |
On DeepSeek-V4.1 decode, evaluate after each layer part and print each part's wall time per token. |
GMLX_DECODE_LAYER_PROFILE=2 |
Also evaluate inside attention and the MoE, so each sub-step is one command buffer in a GPU trace. |
GMLX_DECODE_LAYER_PROFILE_LOG |
With the layer profile, write every mark to this path at exit, for aligning a Metal System Trace. |
GMLX_LAYER_PROFILE_PREFILL=1 |
With the layer profile, also mark the prefill chunks. The per-token figures then average over forward calls. |