Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
212 commits
Select commit Hold shift + click to select a range
65f8f54
server: tell a streaming client when its slot is parked and restored
danielhanchen Sep 5, 2026
601cfe4
cuda: add GGML_CUDA_BATCH_INVARIANT so a row does not depend on its b…
danielhanchen Sep 5, 2026
b5c1029
cuda: bound the batch-invariant split with GGML_CUDA_BATCH_INVARIANT_…
danielhanchen Sep 5, 2026
f3ce972
cuda: add exact concurrency with canonical paged attention
danielhanchen Sep 5, 2026
a94f76f
batch: keep a prompt ubatch to one sequence under LLAMA_EXACT_CONCURR…
danielhanchen Sep 5, 2026
07d82f0
cuda: let exact mode bound the column policy when prompt ubatches are…
danielhanchen Sep 5, 2026
5c6d79e
ggml: add a non-blocking query for backend events
danielhanchen Sep 5, 2026
b048783
llama: coalesce sequence state transfers, and issue them asynchronously
danielhanchen Sep 5, 2026
1d98f93
server: take the park and restore copies off the decode loop
danielhanchen Sep 5, 2026
4814a26
cuda: give every MUL_MAT_ID token the single-token configuration
danielhanchen Sep 6, 2026
7b0d7ed
cuda: leave the top-k routing unfused under GGML_CUDA_BATCH_INVARIANT
danielhanchen Sep 6, 2026
65860ea
cuda: default exact mode to a bound that covers the speculative verif…
danielhanchen Sep 6, 2026
f9323ba
Merge branch 'feat/server-side-preemption-notify' into feat/server-si…
danielhanchen Sep 6, 2026
a29b549
Merge branch 'feat/server-side-preemption-async' into feat/server-sid…
danielhanchen Sep 6, 2026
a3f04ca
Merge branch 'feat/exact-concurrency' into feat/server-side-preemptio…
danielhanchen Sep 6, 2026
d00cb7f
server: refuse n > 1 under exact concurrency instead of aborting in t…
danielhanchen Sep 6, 2026
35097d8
server: plan the kv pool in cells rather than tokens
danielhanchen Sep 6, 2026
e7e88e9
ggml: map the event query onto HIP and MUSA
danielhanchen Sep 6, 2026
d33f04f
llama: require a real event query before copying a sequence asynchron…
danielhanchen Sep 6, 2026
0160ea4
server: wait for the parks still in flight before tearing the context…
danielhanchen Sep 6, 2026
c0d9297
server: charge a resume candidate its own lookahead before admitting it
danielhanchen Sep 6, 2026
cd54f60
llama: report the host memory a transfer holds, not the kind it asked…
danielhanchen Sep 6, 2026
22c90bd
llama: check the size and the flags a sequence transfer is issued with
danielhanchen Sep 6, 2026
e8f8b2f
ggml: stop collecting an error the CUDA event query never sets
danielhanchen Sep 6, 2026
86315ea
ggml: bump the backend API version for the new device interface member
danielhanchen Sep 6, 2026
3cc003a
kv-cache: refuse exact mode when a KV layer is not on the CUDA backend
danielhanchen Sep 6, 2026
6658393
kv-cache: report the cache transformations exact mode cannot do
danielhanchen Sep 6, 2026
b81d8e7
batch: isolate only the prompt sequences, in every memory type
danielhanchen Sep 6, 2026
c7027d6
cuda: derive the exact mode column bound from the decode width
danielhanchen Sep 6, 2026
9cd1222
graph: refuse exact mode on the V-less attention layouts
danielhanchen Sep 6, 2026
b5e9ebd
batchinv: stop the harness from certifying a reduced run
danielhanchen Sep 6, 2026
bba1668
server: do not leave an issued async park holding the room the decode…
danielhanchen Sep 6, 2026
83af5be
server: make the result queue timeout a deadline, so a parked stream …
danielhanchen Sep 6, 2026
888603d
server: do not leave an issued async park holding the room the decode…
danielhanchen Sep 6, 2026
5a791e0
server: make the result queue timeout a deadline, so a parked stream …
danielhanchen Sep 6, 2026
712bee7
kv-cache: maintain page ownership instead of rebuilding it per ubatch
danielhanchen Sep 6, 2026
a2f9c08
server: refuse n > 1 under exact concurrency instead of aborting in t…
danielhanchen Sep 6, 2026
72aca44
memory: let the server ask how many cells an allocation takes
danielhanchen Sep 6, 2026
da8556d
server: plan the kv pool in cells rather than tokens
danielhanchen Sep 6, 2026
1c5aa49
Merge branch 'feat/server-side-preemption-notify' into feat/server-si…
danielhanchen Sep 6, 2026
51eca08
Merge branch 'feat/server-side-preemption-async' into feat/server-sid…
danielhanchen Sep 6, 2026
70d49bf
Merge branch 'feat/exact-concurrency' into feat/server-side-preemptio…
danielhanchen Sep 6, 2026
c6c3cb6
exact: group speculative verify batches and slice the column split
danielhanchen Sep 6, 2026
ef257d7
Merge branch 'feat/exact-concurrency' into feat/server-side-preemptio…
danielhanchen Sep 6, 2026
379ca5d
cuda: run the single-token MUL_MAT_ID configuration over every token …
danielhanchen Sep 6, 2026
abccc6e
Merge branch 'feat/exact-concurrency' into feat/server-side-preemptio…
danielhanchen Sep 6, 2026
2ce1bd3
Merge branch 'feat/server-side-preemption' into feat/exact-concurrency
danielhanchen Sep 6, 2026
a7db626
Merge branch 'feat/server-side-preemption' into feat/server-side-pree…
danielhanchen Sep 6, 2026
2522c59
Merge branch 'feat/server-side-preemption' into feat/server-side-pree…
danielhanchen Sep 6, 2026
f4e4564
batch: group only sets with the same number of tokens left under exac…
danielhanchen Sep 6, 2026
442ffed
Merge branch 'feat/server-side-preemption' into feat/server-side-pree…
danielhanchen Sep 6, 2026
667a654
Merge branch 'feat/server-side-preemption' into feat/exact-concurrency
danielhanchen Sep 6, 2026
3f817d8
Merge branch 'feat/exact-concurrency' into feat/server-side-preemptio…
danielhanchen Sep 6, 2026
71ee8d4
Merge branch 'feat/server-side-preemption' into feat/server-side-pree…
danielhanchen Sep 6, 2026
1a6f7da
exact: refuse by name what the mode cannot run, before it runs
danielhanchen Sep 6, 2026
adeed65
Merge branch 'feat/server-side-preemption' into feat/exact-concurrency
danielhanchen Sep 6, 2026
e8ab02c
Merge branch 'feat/server-side-preemption' into feat/server-side-pree…
danielhanchen Sep 6, 2026
db95586
Merge branch 'feat/exact-concurrency' into feat/server-side-preemptio…
danielhanchen Sep 6, 2026
4e49a05
Merge branch 'feat/server-side-preemption' into feat/server-side-pree…
danielhanchen Sep 6, 2026
da0f9fc
Merge branch 'feat/server-side-preemption' into feat/exact-concurrency
danielhanchen Sep 6, 2026
53553ff
Merge branch 'feat/server-side-preemption' into feat/server-side-pree…
danielhanchen Sep 6, 2026
a552525
Merge branch 'feat/server-side-preemption' into feat/server-side-pree…
danielhanchen Sep 6, 2026
6ea151a
Merge branch 'feat/server-side-preemption-async' into feat/server-sid…
danielhanchen Sep 6, 2026
a643eae
Merge branch 'feat/exact-concurrency' into feat/server-side-preemptio…
danielhanchen Sep 6, 2026
70b874c
Merge branch 'feat/server-side-preemption-async' into feat/server-sid…
danielhanchen Sep 6, 2026
a7e661c
Merge branch 'feat/exact-concurrency' into feat/server-side-preemptio…
danielhanchen Sep 6, 2026
01dfecc
Merge branch 'feat/server-side-preemption' into feat/server-side-pree…
danielhanchen Sep 6, 2026
c89d87d
Merge branch 'feat/server-side-preemption' into feat/exact-concurrency
danielhanchen Sep 6, 2026
c1e5453
Merge branch 'feat/server-side-preemption-async' into feat/server-sid…
danielhanchen Sep 6, 2026
1130aed
Merge branch 'feat/exact-concurrency' into feat/server-side-preemptio…
danielhanchen Sep 6, 2026
47ef8de
Merge branch 'feat/server-side-preemption' into feat/server-side-pree…
danielhanchen Sep 6, 2026
6573242
Merge branch 'feat/server-side-preemption' into feat/exact-concurrency
danielhanchen Sep 6, 2026
e9aeb3a
Merge branch 'feat/server-side-preemption' into feat/server-side-pree…
danielhanchen Sep 6, 2026
5864dae
server: tell the stream about a park made as a last resort
danielhanchen Sep 6, 2026
b89302b
Merge branch 'feat/server-side-preemption-notify' into feat/server-si…
danielhanchen Sep 6, 2026
f8ec566
Merge branch 'feat/server-side-preemption-async' into feat/server-sid…
danielhanchen Sep 6, 2026
cd1cd4e
server: count a slot being restored in the asynchronous lookahead margin
danielhanchen Sep 6, 2026
0c9fc0e
exact: every context reports the widest decode step it can build
danielhanchen Sep 6, 2026
5e0f99a
Merge branch 'feat/exact-concurrency' into feat/server-side-preemptio…
danielhanchen Sep 6, 2026
301f480
Merge branch 'feat/server-side-preemption' into feat/server-side-pree…
danielhanchen Sep 6, 2026
08e10da
Merge branch 'feat/server-side-preemption' into feat/exact-concurrency
danielhanchen Sep 6, 2026
1eef6ef
Merge branch 'feat/server-side-preemption-notify' into feat/server-si…
danielhanchen Sep 6, 2026
03e641e
Merge branch 'feat/server-side-preemption-async' into feat/server-sid…
danielhanchen Sep 6, 2026
3fc8339
Merge branch 'feat/exact-concurrency' into feat/server-side-preemptio…
danielhanchen Sep 6, 2026
0303888
Merge branch 'feat/server-side-preemption' into feat/server-side-pree…
danielhanchen Sep 6, 2026
76baf1a
Merge branch 'feat/server-side-preemption' into feat/server-side-pree…
danielhanchen Sep 6, 2026
a760b00
Merge branch 'feat/server-side-preemption' into feat/server-side-pree…
danielhanchen Sep 6, 2026
67063e4
Merge branch 'feat/server-side-preemption' into feat/exact-concurrency
danielhanchen Sep 6, 2026
01e6715
Merge branch 'feat/server-side-preemption-async' into feat/server-sid…
danielhanchen Sep 6, 2026
1afcfe8
Merge branch 'feat/exact-concurrency' into feat/server-side-preemptio…
danielhanchen Sep 6, 2026
7c8a6d5
Merge branch 'feat/server-side-preemption-notify' into feat/server-si…
danielhanchen Sep 6, 2026
cac5ee6
Merge branch 'feat/server-side-preemption' into feat/server-side-pree…
danielhanchen Sep 6, 2026
46e7fa7
exact: four refusals and one width from review
danielhanchen Sep 6, 2026
7fb42b5
server: keep the park notices of a multi-prompt stream apart
danielhanchen Sep 6, 2026
abbde56
Merge branch 'feat/server-side-preemption-notify' into feat/server-si…
danielhanchen Sep 6, 2026
800e166
Merge branch 'feat/exact-concurrency' into feat/server-side-preemptio…
danielhanchen Sep 6, 2026
bb577b0
Merge branch 'feat/server-side-preemption-notify' into feat/server-si…
danielhanchen Sep 6, 2026
b7ace52
Merge branch 'feat/server-side-preemption' into feat/exact-concurrency
danielhanchen Sep 6, 2026
8d74efb
Merge branch 'feat/server-side-preemption' into feat/server-side-pree…
danielhanchen Sep 6, 2026
53c59a1
Merge branch 'feat/server-side-preemption' into feat/server-side-pree…
danielhanchen Sep 6, 2026
cccc119
Merge branch 'feat/server-side-preemption-async' into feat/server-sid…
danielhanchen Sep 6, 2026
eb42826
Merge branch 'feat/exact-concurrency' into feat/server-side-preemptio…
danielhanchen Sep 6, 2026
eae4624
exact concurrency: refuse a non-causal context with a cache at creati…
danielhanchen Sep 6, 2026
dbd82ca
exact concurrency: the decode width of every context follows the toke…
danielhanchen Sep 6, 2026
42e5369
server: a round with a context shift waits for every park and restore…
danielhanchen Sep 6, 2026
65f6173
Merge feat/server-side-preemption: keep only the shared prefix of a r…
danielhanchen Sep 6, 2026
ab40f16
server: a stream parked before its first token starts with the notice…
danielhanchen Sep 6, 2026
356978a
Merge feat/server-side-preemption: keep only the shared prefix of a r…
danielhanchen Sep 6, 2026
bdb7c6b
Merge feat/server-side-preemption-async
danielhanchen Sep 6, 2026
9560fbf
Merge feat/exact-concurrency
danielhanchen Sep 6, 2026
9391aa7
Merge feat/server-side-preemption-notify
danielhanchen Sep 6, 2026
d4e3fc8
exact concurrency: equal-count grouping stays on for recurrent and hy…
danielhanchen Sep 6, 2026
3306d4b
Merge feat/server-side-preemption: planner accounting for reused slot…
danielhanchen Sep 6, 2026
232f612
Merge feat/exact-concurrency
danielhanchen Sep 6, 2026
6af0d4e
server: a restore landing inside the context-shift wait sends the res…
danielhanchen Sep 6, 2026
ad3856a
Merge feat/server-side-preemption: planner accounting for reused slot…
danielhanchen Sep 6, 2026
0661764
Merge feat/server-side-preemption-notify
danielhanchen Sep 6, 2026
645d406
Merge feat/server-side-preemption-async
danielhanchen Sep 6, 2026
276dd25
Merge feat/server-side-preemption: victim-policy test knob
danielhanchen Sep 6, 2026
7efef20
Merge feat/server-side-preemption: the rotation parks the resident th…
danielhanchen Sep 6, 2026
2ba0dcf
Merge feat/server-side-preemption: the rotation parks the resident th…
danielhanchen Sep 6, 2026
bf00ac3
exact concurrency: soft-capped attention refused at load; width repor…
danielhanchen Sep 6, 2026
3a5e4c7
Merge feat/exact-concurrency
danielhanchen Sep 6, 2026
68a6f3a
Merge feat/server-side-preemption-async
danielhanchen Sep 6, 2026
ecdb0f5
Merge feat/server-side-preemption-notify
danielhanchen Sep 6, 2026
98fe86d
exact concurrency: the setup runs before anything is loaded; one lock…
danielhanchen Sep 6, 2026
3d179fd
Merge feat/server-side-preemption: a parked slot survives an aborted …
danielhanchen Sep 6, 2026
2297d5d
Merge feat/server-side-preemption: a parked slot survives an aborted …
danielhanchen Sep 6, 2026
02a3e11
server: the abort sweep also leaves a slot whose copy is in flight alone
danielhanchen Sep 6, 2026
706d857
Merge feat/exact-concurrency
danielhanchen Sep 6, 2026
bcffb69
Merge remote-tracking branch 'origin/feat/server-side-preemption' int…
danielhanchen Sep 6, 2026
42a4052
Merge feat/server-side-preemption-async
danielhanchen Sep 6, 2026
089fedd
Merge feat/server-side-preemption-notify
danielhanchen Sep 6, 2026
5a13c67
server: asynchronous copies and the rotation, the budget and the cach…
danielhanchen Sep 6, 2026
77d3185
exact concurrency: an isolated ubatch takes only sets that finish in …
danielhanchen Sep 6, 2026
e432b15
Merge feat/server-side-preemption: the leader is measured by what a r…
danielhanchen Sep 6, 2026
4d5734b
Merge origin/feat/exact-concurrency (the base branch merged on the re…
danielhanchen Sep 6, 2026
49c66c5
Merge feat/server-side-preemption: the leader is measured by what a r…
danielhanchen Sep 6, 2026
a06419d
Merge feat/server-side-preemption: the leader is measured by what a r…
danielhanchen Sep 6, 2026
4a7a60c
Merge feat/exact-concurrency
danielhanchen Sep 6, 2026
861a525
Merge feat/server-side-preemption-async
danielhanchen Sep 6, 2026
d72e2a4
Merge feat/server-side-preemption-notify
danielhanchen Sep 6, 2026
82f40df
preempt: post no copies for a transfer that failed part way, park syn…
danielhanchen Sep 6, 2026
2f2258d
exact concurrency: refuse a whole-context restore before it clears th…
danielhanchen Sep 6, 2026
2b4a691
tests: a state transfer that fails one byte short posts no copies, on…
danielhanchen Sep 6, 2026
319f71b
Merge feat/server-side-preemption-async: commit-gated transfers, page…
danielhanchen Sep 6, 2026
60b1b9f
Merge feat/exact-concurrency: restore preflight, width published at c…
danielhanchen Sep 6, 2026
b4a5f18
preempt: say why the asynchronous runway is rounded once rather than …
danielhanchen Sep 6, 2026
a614c25
Merge feat/server-side-preemption-notify: parent and child alone in t…
danielhanchen Sep 6, 2026
faa3dd3
Merge feat/server-side-preemption: parent and child alone in the pool…
danielhanchen Sep 6, 2026
23c9dc2
Merge feat/server-side-preemption: parent and child alone in the pool…
danielhanchen Sep 6, 2026
1d52885
Merge feat/server-side-preemption: parent and child alone in the pool…
danielhanchen Sep 6, 2026
c2e7755
Merge feat/server-side-preemption-async: parent and child alone in th…
danielhanchen Sep 6, 2026
48f7d7c
Merge feat/exact-concurrency: parent and child alone in the pool test
danielhanchen Sep 6, 2026
9e827b5
preempt: a slot whose park buffer comes back pageable parks synchrono…
danielhanchen Sep 6, 2026
aaa9dc0
Merge feat/server-side-preemption-async: a pageable park buffer parks…
danielhanchen Sep 6, 2026
918a8bf
exact concurrency: ask the device whether it can run the paged attent…
danielhanchen Sep 6, 2026
0269811
Merge feat/exact-concurrency: the device is asked whether it runs the…
danielhanchen Sep 6, 2026
a4b62f2
preempt: the graphs that follow a restore wait for its copies, on the…
danielhanchen Sep 6, 2026
0611fd9
Merge feat/server-side-preemption-async: the graphs after a restore w…
danielhanchen Sep 6, 2026
294d2a9
preempt: idle parked RAM is given back when another slot needs to par…
danielhanchen Sep 7, 2026
f737e6d
Merge feat/server-side-preemption-async: idle parked RAM given back; …
danielhanchen Sep 7, 2026
a158200
Merge feat/server-side-preemption: recurrent caches served without pr…
danielhanchen Sep 7, 2026
dffa102
Merge feat/server-side-preemption: recurrent caches served without pr…
danielhanchen Sep 7, 2026
7d77d71
Merge feat/server-side-preemption-async: recurrent caches served with…
danielhanchen Sep 7, 2026
bf0f731
Merge feat/server-side-preemption-notify a158200de
danielhanchen Sep 7, 2026
ce02834
Merge feat/server-side-preemption: a started slot's reservation count…
danielhanchen Sep 7, 2026
012ef75
llama: the copies wait for a fence the context records after every de…
danielhanchen Sep 7, 2026
a5749d1
Merge feat/server-side-preemption: a started slot's reservation count…
danielhanchen Sep 7, 2026
31dd6a9
Merge feat/server-side-preemption-async: the copies wait for a fence …
danielhanchen Sep 7, 2026
a140e80
Merge feat/server-side-preemption-notify ce02834c4
danielhanchen Sep 7, 2026
5ecdba8
Merge feat/server-side-preemption: the shift and the planner inside t…
danielhanchen Sep 7, 2026
a56d49e
Merge feat/server-side-preemption: the shift and the planner inside t…
danielhanchen Sep 7, 2026
1bcae7b
Merge feat/server-side-preemption-async: the shift and the planner in…
danielhanchen Sep 7, 2026
e36a4b6
Merge feat/server-side-preemption-notify 5ecdba815
danielhanchen Sep 7, 2026
02a908b
server: a parked stream keeps a shorter ping interval the request ask…
danielhanchen Sep 7, 2026
4918294
Merge feat/server-side-preemption: what a started slot keeps is decid…
danielhanchen Sep 7, 2026
4b91744
server: a decode that fits goes ahead beside a park in flight; a rest…
danielhanchen Sep 7, 2026
7eff726
llama: staging counts by what a buffer charges; fences installed afte…
danielhanchen Sep 7, 2026
8cb58df
Merge feat/server-side-preemption: what a started slot keeps is decid…
danielhanchen Sep 7, 2026
a23367f
Merge feat/server-side-preemption-async: staging counted by what a bu…
danielhanchen Sep 7, 2026
b0fae41
Merge feat/server-side-preemption-notify 4918294ff
danielhanchen Sep 7, 2026
3475eb0
llama: the shift wait runs before the draft is asked for; the last tr…
danielhanchen Sep 7, 2026
027c86a
Merge feat/server-side-preemption: the resume order read on every load
danielhanchen Sep 7, 2026
03e57da
Merge feat/server-side-preemption: the resume order read on every load
danielhanchen Sep 7, 2026
d3107ae
Merge feat/server-side-preemption-async: the shift wait before the dr…
danielhanchen Sep 7, 2026
f3809e9
Merge feat/server-side-preemption-notify
danielhanchen Sep 7, 2026
801e29a
Merge feat/server-side-preemption: the rotation-budget test keeps its…
danielhanchen Sep 7, 2026
114e230
Merge feat/server-side-preemption: the rotation-budget test keeps its…
danielhanchen Sep 7, 2026
0d39b88
Merge feat/server-side-preemption: the rotation-budget test keeps its…
danielhanchen Sep 7, 2026
929809f
Merge feat/server-side-preemption: the resume order belongs to the co…
danielhanchen Sep 7, 2026
ebfa47b
llama: a context freed with live transfers drains and disowns them; t…
danielhanchen Sep 7, 2026
b1a31b4
Merge feat/server-side-preemption: the resume order belongs to the co…
danielhanchen Sep 7, 2026
bb24e88
Merge feat/server-side-preemption-async: live transfers drained at te…
danielhanchen Sep 7, 2026
7fdb58b
Merge feat/server-side-preemption-notify 929809ffa
danielhanchen Sep 7, 2026
58c6e33
Merge /mnt/disks/unslothai/daniel3/workspace_12/llamacpp_fork into fe…
danielhanchen Sep 7, 2026
a33c563
Merge /mnt/disks/unslothai/daniel3/workspace_12/llamacpp_fork into fe…
danielhanchen Sep 7, 2026
f8a5338
Merge feat/server-side-preemption-notify a33c56397: a started slot co…
danielhanchen Sep 7, 2026
1bf8519
Merge /mnt/disks/unslothai/daniel3/workspace_12/llamacpp_async_park i…
danielhanchen Sep 7, 2026
b4b0f9b
exact concurrency: shorter comments
danielhanchen Sep 7, 2026
90a5094
server : validate a started slot's prompt before it can be parked
danielhanchen Sep 7, 2026
773db2e
Merge /mnt/disks/unslothai/daniel3/workspace_12/llamacpp_notify into …
danielhanchen Sep 7, 2026
474569c
Merge feat/exact-concurrency b4b0f9bd7: shorter comments; the conflic…
danielhanchen Sep 7, 2026
f8fdf06
server, llama, ggml : shorter comments across the preemption work
danielhanchen Sep 7, 2026
951a219
server : drop the unrelated tooling edits from the preemption change
danielhanchen Sep 7, 2026
57efd21
server : share the park and resume bookkeeping between the copy paths
danielhanchen Sep 7, 2026
7e424ad
server : count the kv reserve in one pass over the slots
danielhanchen Sep 7, 2026
7549c68
tests : share the preemption server setup and the prompts
danielhanchen Sep 7, 2026
4cf9baf
llama : build the asynchronous state io on the host io
danielhanchen Sep 7, 2026
00855c2
server : drop the wrappers that only ever had one reader
danielhanchen Sep 7, 2026
bb510f5
server : drive a slot's two transfers through one helper
danielhanchen Sep 7, 2026
09cecf4
server, llama, ggml : fewer comments
danielhanchen Sep 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions common/arg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1304,6 +1304,11 @@ bool common_params_parse(int argc, char ** argv, common_params & params, llama_e
exit(0);
}
params.lr.init();

if (!common_exact_concurrency_init(ctx_arg.params)) {
ctx_arg.params = params_org;
return false;
}
} catch (const std::invalid_argument & ex) {
fprintf(stderr, "%s\n", ex.what());
ctx_arg.params = params_org;
Expand Down Expand Up @@ -1717,6 +1722,16 @@ common_params_context common_params_parser_init(common_params & params, llama_ex
params.preempt_ram_mib = value;
}
).set_env("LLAMA_ARG_PREEMPT_RAM").set_examples({LLAMA_EXAMPLE_SERVER}));
add_opt(common_arg(
{"--preempt-async"},
{"--no-preempt-async"},
"copy a parked sequence out of and back into the KV cache on a stream of its own, so the "
"slots that keep running do not wait for it (default: enabled, needs a backend that can "
"copy asynchronously, otherwise the copies are synchronous as before)",
[](common_params & params, bool value) {
params.preempt_async = value;
}
).set_env("LLAMA_ARG_PREEMPT_ASYNC").set_examples({LLAMA_EXAMPLE_SERVER}));
add_opt(common_arg(
{"-kvu", "--kv-unified"},
{"-no-kvu", "--no-kv-unified"},
Expand Down
72 changes: 72 additions & 0 deletions common/common.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "ggml.h"
#include "ggml-backend.h"
#include "gguf.h"

#include "build-info.h"
Expand Down Expand Up @@ -1289,6 +1290,12 @@ struct common_init_result::impl {

common_init_result::common_init_result(common_params & params, bool model_only) :
pimpl(new impl{}) {
// [TAG_EXACT_CONCURRENCY] before any context exists, so one is never created under a figure the explicit bound does not cover
if (!model_only && !common_exact_concurrency_init(params)) {
COM_ERR("%s", "LLAMA_EXACT_CONCURRENCY: refusing to load the model, see the error above\n");
return;
}

auto mparams = common_model_params_to_llama(params);
auto cparams = common_context_params_to_llama(params);

Expand Down Expand Up @@ -1433,6 +1440,71 @@ std::vector<llama_adapter_lora_ptr> & common_init_result::lora() {
return pimpl->lora;
}

// [TAG_EXACT_CONCURRENCY]
bool common_exact_concurrency() {
static const bool enabled = []() {
const char * val = getenv("LLAMA_EXACT_CONCURRENCY");
return val && atoi(val) != 0;
}();

return enabled;
}

int common_exact_decode_width(const common_params & params) {
const int64_t n_slots = std::max(1, params.n_parallel);

const int64_t n_draft = std::max(0, (int) common_speculative_n_max(&params.speculative));

// the product is handed to a backend as an int; one that overflows is reported, not wrapped
const int64_t n_cols = n_slots*(1 + n_draft);

return n_cols > INT32_MAX ? -1 : (int) n_cols;
}

bool common_exact_concurrency_init(const common_params & params) {
if (!common_exact_concurrency()) {
return true;
}

// DFlash drafting turns causal attention off on its draft context, which the paged attention needs; say so instead of asserting in the graph. DSpark is the same.
for (const auto type : params.speculative.types) {
if (type == COMMON_SPECULATIVE_TYPE_DRAFT_DFLASH || type == COMMON_SPECULATIVE_TYPE_DRAFT_DSPARK) {
COM_ERR("%s", "LLAMA_EXACT_CONCURRENCY does not support --spec-type draft-dflash or draft-dspark: both disable causal attention on the draft, which the paged attention needs\n");
return false;
}
}

const int n_cols = common_exact_decode_width(params);

if (n_cols < 0) {
COM_ERR("LLAMA_EXACT_CONCURRENCY: a decode step of %d slots with %d draft tokens each is too wide to report\n",
std::max(1, params.n_parallel), std::max(0, (int) common_speculative_n_max(&params.speculative)));
return false;
}

const char * bound = getenv("GGML_CUDA_BATCH_INVARIANT_MAX_COLS");
if (bound) {
const int max_cols = atoi(bound);
if (max_cols > 0 && max_cols < n_cols) {
COM_ERR("GGML_CUDA_BATCH_INVARIANT_MAX_COLS is %d but LLAMA_EXACT_CONCURRENCY needs at "
"least %d to cover a decode step of %d slots, above which a matmul is left "
"batched and its rows depend on the other rows in the ubatch. Raise it to %d, "
"set it to 0 for no bound, or unset it to let it default to %d.\n",
max_cols, n_cols, std::max(1, params.n_parallel), n_cols, n_cols);
return false;
}
}

// the batch splitter isolates prompts by width, so tell it how wide one sequence's decode step is; this also covers a caller that decodes before creating a context
if (!llama_set_exact_decode_tokens((uint32_t) (n_cols / std::max(1, params.n_parallel))) ||
!llama_set_exact_decode_width((uint32_t) n_cols)) {
COM_ERR("%s", "LLAMA_EXACT_CONCURRENCY: the decode width could not be reported, see the error above\n");
return false;
}

return true;
}

common_init_result_ptr common_init_from_params(common_params & params, bool model_only) {
common_init_result_ptr res(new common_init_result(params, model_only));

Expand Down
9 changes: 9 additions & 0 deletions common/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,7 @@ struct common_params {
int32_t checkpoint_min_step = 8192; // minimum spacing between context checkpoints
int32_t cache_ram_mib = 8192; // -1 = no limit, 0 - disable, 1 = 1 MiB, etc.
int32_t preempt_ram_mib = 8192; // host RAM for parked (preempted) sequences: -1 = no limit, 0 = disable preemption
bool preempt_async = true; // park and restore on a stream of their own, off the decode loop

std::string hostname = "127.0.0.1";
std::string public_path = ""; // NOLINT
Expand Down Expand Up @@ -931,6 +932,14 @@ using common_init_result_ptr = std::unique_ptr<common_init_result>;

common_init_result_ptr common_init_from_params(common_params & params, bool model_only = false);

// [TAG_EXACT_CONCURRENCY] true when LLAMA_EXACT_CONCURRENCY is set for this process
bool common_exact_concurrency();

int common_exact_decode_width(const common_params & params);

// report that width to the CUDA backend, refusing a smaller explicit GGML_CUDA_BATCH_INVARIANT_MAX_COLS; false if the configuration must not run
bool common_exact_concurrency_init(const common_params & params);

struct llama_model_params common_model_params_to_llama ( common_params & params);
struct llama_context_params common_context_params_to_llama(const common_params & params);

Expand Down
6 changes: 6 additions & 0 deletions ggml/include/ggml-backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ extern "C" {
GGML_API size_t ggml_backend_buffer_get_alloc_size(ggml_backend_buffer_t buffer, const struct ggml_tensor * tensor);
GGML_API void ggml_backend_buffer_clear (ggml_backend_buffer_t buffer, uint8_t value);
GGML_API bool ggml_backend_buffer_is_host (ggml_backend_buffer_t buffer);
// whether the buffer copies a strided set of rows in one call (see ggml_backend_tensor_set_2d); without it the generic path issues one transfer per row
GGML_API bool ggml_backend_buffer_supports_2d (ggml_backend_buffer_t buffer);
GGML_API void ggml_backend_buffer_set_usage (ggml_backend_buffer_t buffer, enum ggml_backend_buffer_usage usage);
GGML_API enum ggml_backend_buffer_usage ggml_backend_buffer_get_usage (ggml_backend_buffer_t buffer);
GGML_API ggml_backend_buffer_type_t ggml_backend_buffer_get_type (ggml_backend_buffer_t buffer);
Expand Down Expand Up @@ -125,6 +127,8 @@ extern "C" {
GGML_API void ggml_backend_event_free(ggml_backend_event_t event);
GGML_API void ggml_backend_event_record(ggml_backend_event_t event, ggml_backend_t backend);
GGML_API void ggml_backend_event_synchronize(ggml_backend_event_t event);
// non-blocking: true once everything recorded before the event has completed. Backends without a query implementation fall back to a blocking synchronize.
GGML_API bool ggml_backend_event_query(ggml_backend_event_t event);
GGML_API void ggml_backend_event_wait(ggml_backend_t backend, ggml_backend_event_t event);

//
Expand Down Expand Up @@ -190,6 +194,8 @@ extern "C" {
GGML_API ggml_backend_buffer_t ggml_backend_dev_buffer_from_host_ptr(ggml_backend_dev_t device, void * ptr, size_t size, size_t max_tensor_size);

GGML_API bool ggml_backend_dev_supports_op(ggml_backend_dev_t device, const struct ggml_tensor * op);
// whether ggml_backend_event_query() on this device really is non-blocking, rather than falling back to a blocking synchronize
GGML_API bool ggml_backend_dev_supports_event_query(ggml_backend_dev_t device);
GGML_API bool ggml_backend_dev_supports_buft(ggml_backend_dev_t device, ggml_backend_buffer_type_t buft);
GGML_API bool ggml_backend_dev_offload_op(ggml_backend_dev_t device, const struct ggml_tensor * op);

Expand Down
3 changes: 3 additions & 0 deletions ggml/include/ggml-cuda.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ GGML_BACKEND_API void ggml_backend_cuda_get_device_description(int device, char
GGML_BACKEND_API void ggml_backend_cuda_get_device_memory(int device, size_t * free, size_t * total);

GGML_BACKEND_API bool ggml_backend_cuda_register_host_buffer(void * buffer, size_t size);

// [TAG_EXACT_CONCURRENCY] report the widest ubatch a decode step of this process can build, so the column policy covers it; call before the first graph is computed
GGML_BACKEND_API void ggml_backend_cuda_set_exact_decode_width(int n_cols);
GGML_BACKEND_API void ggml_backend_cuda_unregister_host_buffer(void * buffer);

GGML_BACKEND_API ggml_backend_reg_t ggml_backend_cuda_reg(void);
Expand Down
5 changes: 4 additions & 1 deletion ggml/src/ggml-backend-impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
extern "C" {
#endif

#define GGML_BACKEND_API_VERSION 2
#define GGML_BACKEND_API_VERSION 3

//
// Backend buffer type
Expand Down Expand Up @@ -200,6 +200,9 @@ extern "C" {
ggml_backend_event_t (*event_new) (ggml_backend_dev_t dev);
void (*event_free) (ggml_backend_dev_t dev, ggml_backend_event_t event);
void (*event_synchronize) (ggml_backend_dev_t dev, ggml_backend_event_t event);

// (optional) non-blocking completion test for an event. Kept last: a missing entry is NULL and ggml_backend_event_query() then blocks instead.
bool (*event_query) (ggml_backend_dev_t dev, ggml_backend_event_t event);
};

struct ggml_backend_device {
Expand Down
1 change: 1 addition & 0 deletions ggml/src/ggml-backend-meta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ static const ggml_backend_device_i ggml_backend_meta_device_iface = {
/* .event_new = */ nullptr,
/* .event_free = */ nullptr,
/* .event_synchronize = */ nullptr,
/* .event_query = */ NULL,
};

static bool ggml_backend_dev_is_meta(ggml_backend_dev_t dev) {
Expand Down
21 changes: 21 additions & 0 deletions ggml/src/ggml-backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@ bool ggml_backend_buffer_is_host(ggml_backend_buffer_t buffer) {
return ggml_backend_buft_is_host(ggml_backend_buffer_get_type(buffer));
}

bool ggml_backend_buffer_supports_2d(ggml_backend_buffer_t buffer) {
return buffer->iface.set_tensor_2d != NULL && buffer->iface.get_tensor_2d != NULL;
}

void ggml_backend_buffer_set_usage(ggml_backend_buffer_t buffer, enum ggml_backend_buffer_usage usage) {
GGML_ASSERT(buffer);
buffer->usage = usage;
Expand Down Expand Up @@ -551,6 +555,18 @@ void ggml_backend_event_synchronize(ggml_backend_event_t event) {
event->device->iface.event_synchronize(event->device, event);
}

bool ggml_backend_event_query(ggml_backend_event_t event) {
GGML_ASSERT(event);

if (event->device->iface.event_query == NULL) {
// no way to ask: the honest answer is to wait for it and then say yes
ggml_backend_event_synchronize(event);
return true;
}

return event->device->iface.event_query(event->device, event);
}

void ggml_backend_event_wait(ggml_backend_t backend, ggml_backend_event_t event) {
GGML_ASSERT(backend);
GGML_ASSERT(backend->iface.event_wait != NULL);
Expand Down Expand Up @@ -627,6 +643,11 @@ bool ggml_backend_dev_supports_op(ggml_backend_dev_t device, const struct ggml_t
return device->iface.supports_op(device, op);
}

bool ggml_backend_dev_supports_event_query(ggml_backend_dev_t device) {
GGML_ASSERT(device);
return device->iface.event_query != NULL;
}

bool ggml_backend_dev_supports_buft(ggml_backend_dev_t device, ggml_backend_buffer_type_t buft) {
GGML_ASSERT(device);
return device->iface.supports_buft(device, buft);
Expand Down
1 change: 1 addition & 0 deletions ggml/src/ggml-blas/ggml-blas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ static const struct ggml_backend_device_i ggml_backend_blas_device_i = {
/* .event_new = */ NULL,
/* .event_free = */ NULL,
/* .event_synchronize = */ NULL,
/* .event_query = */ NULL,
};

// backend reg interface
Expand Down
5 changes: 5 additions & 0 deletions ggml/src/ggml-cann/ggml-cann.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2656,6 +2656,10 @@ static bool ggml_backend_cann_supports_op(ggml_backend_dev_t dev, const ggml_ten
return true;
case GGML_OP_FLASH_ATTN_EXT:
{
// [TAG_EXACT_CONCURRENCY] src[5] is the page table, which only the CUDA backend reads
if (op->src[5]) {
return false;
}
#ifdef ASCEND_310P
// FA not support on 310p device
return false;
Expand Down Expand Up @@ -2948,6 +2952,7 @@ static const ggml_backend_device_i ggml_backend_cann_device_interface = {
/* .event_new = */ ggml_backend_cann_device_event_new,
/* .event_free = */ ggml_backend_cann_device_event_free,
/* .event_synchronize = */ ggml_backend_cann_device_event_synchronize,
/* .event_query = */ NULL,
};

// backend reg
Expand Down
2 changes: 2 additions & 0 deletions ggml/src/ggml-cpu/ggml-cpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@ static bool ggml_backend_cpu_device_supports_op(ggml_backend_dev_t dev, const st
return ggml_is_contiguous(op->src[0]);
case GGML_OP_SSM_SCAN:
return ggml_get_op_params_i32(op, 0) == 1 || op->src[3]->ne[0] == 1;
// [TAG_EXACT_CONCURRENCY] note: FLASH_ATTN_EXT with src[5], the page table, is deliberately still accepted: the CPU ignores it, but it is the reference test-backend-ops uses
default:
return true;
}
Expand All @@ -500,6 +501,7 @@ static const struct ggml_backend_device_i ggml_backend_cpu_device_i = {
/* .event_new = */ NULL,
/* .event_free = */ NULL,
/* .event_synchronize = */ NULL,
/* .event_query = */ NULL,
};

// CPU backend - backend (reg)
Expand Down
5 changes: 5 additions & 0 deletions ggml/src/ggml-cuda/common.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@

#define GGML_CUDA_CC_PASCAL 600
#define GGML_CUDA_CC_DP4A 610 // minimum compute capability for __dp4a, an intrinsic for byte-wise dot products
// [TAG_BATCH_INVARIANT] 0 = off, 1 = split every batched matmul, 2 = split only where it changes bits
int ggml_cuda_batch_invariant();
// widest batch the split applies to, 0 = no bound; bounding it gives up prompt-phase invariance only
int ggml_cuda_batch_invariant_max_cols();

#define GGML_CUDA_CC_VOLTA 700
#define GGML_CUDA_CC_TURING 750
#define GGML_CUDA_CC_AMPERE 800
Expand Down
13 changes: 11 additions & 2 deletions ggml/src/ggml-cuda/fattn-common.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -1091,7 +1091,9 @@ void launch_fattn(
// Optional optimization where the mask is scanned to determine whether part of the calculation can be skipped.
// Only worth the overhead if there is at lease one FATTN_KQ_STRIDE x FATTN_KQ_STRIDE square to be skipped or
// multiple sequences of possibly different lengths.
if (mask && K->ne[1] % FATTN_KQ_STRIDE == 0 && (Q->ne[1] >= 1024 || Q->ne[3] > 1)) {
// [TAG_BATCH_INVARIANT] without this scan the KV loop runs to K->ne[1], which grows with the other sequences; the mask bounds it by the sequence's own extent
const bool batch_invariant_KV_max = ggml_cuda_batch_invariant() != 0;
if (!dst->src[5] && mask && K->ne[1] % FATTN_KQ_STRIDE == 0 && (Q->ne[1] >= 1024 || Q->ne[3] > 1 || batch_invariant_KV_max)) {
const int64_t s31 = mask->nb[1] / sizeof(half2);
const int64_t s33 = mask->nb[3] / sizeof(half2);

Expand Down Expand Up @@ -1148,6 +1150,13 @@ void launch_fattn(
if (ntiles_dst % blocks_num.x != 0) { // Fixup is only needed if the SMs work on fractional tiles.
dst_tmp_meta.alloc((size_t(blocks_num.x) * ncols * (2 + DV/2)));
}
} else if (dst->src[5] || ggml_cuda_batch_invariant()) {
// [TAG_BATCH_INVARIANT] the KV split between blocks, and so the order the partials combine in, follows K->ne[1]: pin it to one block per tile
parallel_blocks = 1;

blocks_num.x = ntiles_x;
blocks_num.y = parallel_blocks;
blocks_num.z = ntiles_z_gqa*K->ne[2]*Q->ne[3];
} else {
// parallel_blocks must not be larger than what the tensor size allows:
parallel_blocks = std::min(parallel_blocks, ntiles_KV);
Expand Down Expand Up @@ -1214,7 +1223,7 @@ void launch_fattn(
V_data,
mask ? ((const char *) mask->data) : nullptr,
sinks ? ((const char *) sinks->data) : nullptr,
KV_max.ptr,
dst->src[5] ? (const int *) dst->src[5]->data : KV_max.ptr,
!stream_k && parallel_blocks > 1 ? dst_tmp.ptr : (float *) KQV->data, dst_tmp_meta.ptr,
scale, max_bias, m0, m1, n_head_log2, logit_softcap,
Q->ne[0], ne01, Q->ne[2], Q->ne[3], Q->nb[1], Q->nb[2], Q->nb[3],
Expand Down
17 changes: 14 additions & 3 deletions ggml/src/ggml-cuda/fattn-vec.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ static constexpr __device__ int ggml_cuda_fattn_vec_get_nthreads_device() {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpass-failed"
#endif // __clang__
template<int D, int ncols, ggml_type type_K, ggml_type type_V, bool use_logit_softcap> // D == head size
template<int D, int ncols, ggml_type type_K, ggml_type type_V, bool use_logit_softcap, bool paged = false> // D == head size
__launch_bounds__(ggml_cuda_fattn_vec_get_nthreads_device(), 1)
static __global__ void flash_attn_ext_vec(
const char * Q_ptr,
Expand Down Expand Up @@ -247,13 +247,24 @@ static __global__ void flash_attn_ext_vec(
#endif // V_DOT2_F32_F16_AVAILABLE
}

const int k_VKQ_max = KV_max ? KV_max[sequence*gridDim.x + blockIdx.x] : ne11;
// in the paged specialization KV_max carries [count, physical page IDs...] per query; the loop and each warp's recurrence follow logical positions, never physical addresses
static_assert(!paged || ncols == 1, "paged attention has one query per block");
const int * pages = paged ? KV_max + (sequence*int(ne01.z) + ic0)*(1 + ne11/FATTN_KQ_STRIDE) : nullptr;
const int k_VKQ_max = paged ? pages[0]*FATTN_KQ_STRIDE : (KV_max ? KV_max[sequence*gridDim.x + blockIdx.x] : ne11);
const char * K_base = K;
const char * V_base = V;
const half * mask_base = maskh;
K += blockIdx.y*nthreads * nb11;
V += blockIdx.y*nthreads * nb21;
maskh += blockIdx.y*nthreads;
for (int k_VKQ_0 = blockIdx.y*nthreads; k_VKQ_0 < k_VKQ_max; k_VKQ_0 += gridDim.y*nthreads,
// Increment pointers after each loop:
K += gridDim.y*nthreads*nb11, V += gridDim.y*nthreads*nb21, maskh += gridDim.y*nthreads) {
if constexpr (paged) {
const int physical = pages[1 + k_VKQ_0/FATTN_KQ_STRIDE]*FATTN_KQ_STRIDE + k_VKQ_0%FATTN_KQ_STRIDE;
K = K_base + int64_t(physical)*nb11;
V = V_base + int64_t(physical)*nb21;
maskh = mask_base + physical;
}

// Calculate KQ tile and keep track of new maximum KQ values:
float KQ_reg[ncols]; // KQ in registers.
Expand Down
Loading
Loading