[fix](kt-sft): scale chunked_prefill_size by the per-device batch size - #2180
Open
devangpratap wants to merge 1 commit into
Open
[fix](kt-sft): scale chunked_prefill_size by the per-device batch size#2180devangpratap wants to merge 1 commit into
devangpratap wants to merge 1 commit into
Conversation
devangpratap
force-pushed
the
fix-2150-chunked-prefill-batch
branch
from
August 28, 2026 15:55
1772811 to
5a6b39e
Compare
`chunked_prefill_size` is sized from `kt_model_max_length`, which
LLaMA-Factory populates from `cutoff_len`, a per-sequence bound. The
rank-0 buffer already scales by `distributed_world_size`, but the
trainer flattens a batch before the kernel sees it
(`qlen = batch_size * seq_len`, sft/layer.py), and batch is precisely
what grows qlen on each rank. So the buffer is undersized by exactly
the batch factor and `_validate_forward_inputs` raises for any
`per_device_train_batch_size > 1`:
ValueError: qlen (1168) exceeds chunked_prefill_size (1024).
Add a `kt_train_batch_size` config field, following the existing
`ACCELERATE_KT_*` pattern, and multiply the rank-0 buffer by it.
Defaults to 1, so current behaviour is unchanged.
The AMX consequence is the substantive one: at batch 1 with 256 experts
and 8 experts per token, each expert's GEMM gets roughly 6 rows against
an `_AMX_M_STEP` of 32, so the tile runs mostly padded.
Fixes kvcache-ai#2150
devangpratap
force-pushed
the
fix-2150-chunked-prefill-batch
branch
from
August 28, 2026 16:33
5a6b39e to
296edac
Compare
Contributor
Author
|
@yyj6666667 could I get the Tagging you rather than @jdai0 since you picked up #2150. The change is small: The new test runs without a build or AMX hardware, it loads |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Fixes #2150
chunked_prefill_sizeis sized fromkt_model_max_length, which LLaMA-Factory populates fromcutoff_len— a per-sequence bound. The rank-0 buffer already scales bydistributed_world_size, but the trainer flattens a batch before the kernel ever sees it (qlen = batch_size * seq_len,sft/layer.py), and batch is precisely what growsqlenon each rank. So the buffer is undersized by exactly the batch factor and_validate_forward_inputsraises for anyper_device_train_batch_size > 1:The chain on current
main:This adds a
kt_train_batch_sizefield toKTConfigand multiplies the rank-0 buffer by it, alongside the existing world-size factor. It follows the existing config idiom, so it is settable throughmodel_argsorACCELERATE_KT_TRAIN_BATCH_SIZE, and defaults to 1 — current behaviour is unchanged.As the issue notes,
ACCELERATE_KT_MODEL_MAX_LENGTHis not a usable lever: LLaMA-Factory overwrites it fromcutoff_lenbefore kt reads it, soconfig.py'sif ... is Nonefallback never fires.ACCELERATE_KT_TRAIN_BATCH_SIZEis a separate name and is not overwritten.The AMX consequence is the substantive part. At batch 1, with 256 experts and
num_experts_per_tok: 8, each expert's GEMM gets roughlytokens * 8 / 256 ≈ 6rows against_AMX_M_STEP = 32, so the tile runs mostly padded. Batch 8 brings that to ~48 and fills it.What sets
kt_train_batch_sizeWorth being upfront: nothing in this repo populates it automatically, so as of this PR it is a lever the user sets, not an auto-derived value. That is deliberate —
per_device_train_batch_sizelives ontraining_args, and neithertraining_argsnorget_kt_config_dictexists anywhere in kt-kernel (_build_kt_plugin_from_argsonly receivesmodel_argsandfinetuning_args), so auto-deriving it is a LLaMA-Factory-side change, not one I can make here.What this PR does give you:
ACCELERATE_KT_MODEL_MAX_LENGTHis overwritten fromcutoff_lenbefore kt reads it and the only remaining knob iscutoff_lenitselfos.environ["ACCELERATE_KT_MODEL_MAX_LENGTH"] = str(cutoff_len); settingACCELERATE_KT_TRAIN_BATCH_SIZEnext to it is one line and needs nothing further hereHappy to send that LLaMA-Factory patch too if you point me at the fork you build against.
Memory
The buffer grows by the batch factor, so it is worth a sanity check. At
cutoff_len1024 and batch 8 the rank-0 buffer goes to 8192, still comfortably under thechunked_prefill_size=25600used in this repo's own SFT example inpython/experts.py. Default stays 1, so nothing changes for anyone who does not opt in.Scope
Kept to the sizing bug. The issue also notes that a YAML
model_max_length:is clobbered atllamafactory/hparams/parser.py:609— that is in LLaMA-Factory, not this repo, so it is out of scope here.Testing
Added
kt-kernel/test/test_sft_chunked_prefill_size.py, covering the default (batch 1, unchanged), the exact case from the issue (cutoff_len 1024 at batch 2, 4 and 8), composition withdistributed_world_size, the env-var override, and themax_position_embeddingsfallback.It loads
sft/config.pyunder a synthetic parent package rather than importingkt_kernel, whose__init__loads the compiled extension — so it runs without a build and without AMX hardware:Verified it is a real regression test: with the two source files reverted it exits 1, and exits 0 once they are restored.
I do not have a Sapphire Rapids machine, so I have not run an end-to-end fine-tune at batch > 1. The reporter's traceback plus the three files above are the evidence for the sizing itself.
Before submitting