grammar : coalesce find + insert into a single insert and adjust move/copy mechanics (#26885)

1) Combine two consecutive lookups (find + insert) into a single insert-attempt/lookup routine so that we don't per
form two O(log(n)) lookup operations in a row anymore -- we only need to do it once and then see if the insert succeeded.
2) Instead of copying every potential stack (expensive) and then moving it (cheap) to new_stacks when it's a final output state, we switch the order so that we move every potential stack (cheap), and then only copy it (expensive) to new stacks when it's a final output state. There are a LOT of intermediate states that get generated, and unless they become final output states, then all of these expensive intermediate copies are wasted.

Before: lookup -> lookup/insert + copy -> optional move to output
New: lookup/insert + move -> optional copy to output
This commit is contained in:
Clint Herron
2026-09-13 17:56:46 -04:00
committed by GitHub
parent 5f436dddb4
commit 7a16a6ce32
+6 -5
View File
@@ -871,17 +871,18 @@ static void llama_grammar_advance_stack(
std::set<llama_grammar_stack, decltype(stack_cmp)> seen(stack_cmp);
while (!todo.empty()) {
llama_grammar_stack curr_stack = std::move(todo.back());
llama_grammar_stack curr_stack_candidate = std::move(todo.back());
todo.pop_back();
if (seen.find( curr_stack) != seen.end()) {
auto [curr_stack_it, inserted] = seen.insert(std::move(curr_stack_candidate));
if (!inserted) {
continue;
}
seen.insert(curr_stack);
const llama_grammar_stack & curr_stack = *curr_stack_it;
if (curr_stack.empty()) {
if (std::find(new_stacks.begin(), new_stacks.end(), curr_stack) == new_stacks.end()) {
new_stacks.emplace_back(std::move(curr_stack));
new_stacks.emplace_back(curr_stack);
}
continue;
}
@@ -924,7 +925,7 @@ static void llama_grammar_advance_stack(
case LLAMA_GRETYPE_TOKEN_NOT:
if (std::find(new_stacks.begin(), new_stacks.end(), curr_stack) == new_stacks.end()) {
// only add the stack if it's not a duplicate of one we already have
new_stacks.emplace_back(std::move(curr_stack));
new_stacks.emplace_back(curr_stack);
}
break;
default: