liblloyal 1.0.0
Branched Inference for llama.cpp
Loading...
Searching...
No Matches
lloyal::branch::BranchStore Class Reference

Handle table and batched decode orchestrator for branch management. More...

#include <lloyal/branch.hpp>

Classes

struct  Allocation
 Result of allocate(): a slot handle + its leased seq_id. More...
 

Public Member Functions

 BranchStore (size_t initial_capacity=16)
 Construct a branch store with initial slot capacity.
 
 ~BranchStore ()
 Destructor — frees CPU resources.
 
Allocation allocate ()
 Allocate a branch slot + KV lease atomically.
 
void release (BranchHandle handle)
 Release a branch slot + evict its KV lease.
 
void init_tenancy (llama_context *ctx)
 Initialize KV tenancy after context creation.
 
void drain ()
 Explicit teardown — evict all leases while context is alive.
 
void retainOnly (BranchHandle winner)
 Keep only the winner — nuclear KV + CPU cleanup.
 
void fast_forward (BranchHandle parent, BranchHandle child)
 Fast-forward parent to child: the child's state becomes the parent's.
 
size_t available () const
 Number of vacant seq_ids available for acquisition.
 
KvPressure kv_pressure () const
 KV cache pressure snapshot — O(1), no tree walking.
 
void add_cells_used (uint32_t n)
 Increment cells_used counter (for standalone prefill/step outside BranchStore methods)
 
BranchHandle parent (BranchHandle h) const
 Get a branch's parent handle.
 
llama_pos fork_head (BranchHandle h) const
 Get a branch's fork head (parent position at fork time)
 
const std::vector< BranchHandle > & children (BranchHandle h) const
 Get a branch's child handles.
 
bool isLeaf (BranchHandle h) const
 Test whether a branch is a leaf (no children)
 
bool isActive (BranchHandle h) const
 Test whether a branch holds a KV lease.
 
BranchState * get (BranchHandle handle)
 Look up branch state by handle.
 
const BranchState * get (BranchHandle handle) const
 Look up branch state by handle.
 
template<SamplingParamsLike P>
SamplerChainHandle create_sampler (const P &params, int32_t n_vocab)
 Create a sampler chain and register it.
 
SamplerChainHandle clone_sampler (SamplerChainHandle h)
 Clone a sampler chain (for fork)
 
void free_sampler (SamplerChainHandle h)
 Free a sampler chain.
 
llama_sampler * get_sampler_chain (SamplerChainHandle h) const
 Dereference a sampler chain handle (non-owning)
 
bool sampler_has_dist (SamplerChainHandle h) const
 Check if a sampler chain ends with dist (stochastic) or greedy.
 
GrammarHandle create_grammar (const llama_model *model, const char *grammar_str, const char *root="root")
 Create a grammar sampler and register it.
 
GrammarHandle create_grammar_lazy (const llama_model *model, const char *grammar_str, const std::vector< std::string > &trigger_patterns, const std::vector< llama_token > &trigger_tokens, const char *root="root")
 Create a lazy grammar (unconstrained until trigger fires)
 
GrammarHandle clone_grammar (GrammarHandle h)
 Clone a grammar (for fork)
 
void free_grammar (GrammarHandle h)
 Free a grammar.
 
llama_sampler * get_grammar_sampler (GrammarHandle h) const
 Dereference a grammar handle (non-owning)
 
MetricsHandle create_metrics ()
 Create a metrics tracker and register it.
 
MetricsHandle clone_metrics (MetricsHandle h)
 Clone a metrics tracker (for fork)
 
void free_metrics (MetricsHandle h)
 Free a metrics tracker.
 
void add_model_surprisal (MetricsHandle h, float surprisal)
 Add model-level surprisal to a metrics tracker.
 
void add_sampling_surprisal (MetricsHandle h, float surprisal)
 Add sampling-level surprisal to a metrics tracker.
 
float get_model_ppl (MetricsHandle h) const
 Get model-level perplexity from a metrics tracker.
 
float get_sampling_ppl (MetricsHandle h) const
 Get sampling-level perplexity from a metrics tracker.
 
void decode_each (std::span< const DecodeEachItem > items)
 Decode one token per branch in a single GPU dispatch.
 
void decode_scatter (std::span< const DecodeScatterItem > items)
 Decode variable token counts per branch with auto-chunking.
 
void decode_embd (BranchHandle handle, const float *rows, int32_t n_tokens, int32_t n_embd_inp, llama_pos n_pos, const llama_pos *pos, int32_t n_pos_per_embd, bool non_causal, bool want_logits)
 Decode embedding rows into ONE branch's KV (multimodal ingress)
 
DecodeSegmentsResult decode_segments (BranchHandle handle, decode::SegmentSource &source, const std::function< void(const decode::SegmentProgress &)> &on_progress={})
 Prefill a heterogeneous segment sequence into ONE branch.
 
void merge_logits (BranchHandle dst_handle, std::span< const BranchHandle > expert_handles, float alpha)
 Merge experts' logits_snapshot into dst's logits_snapshot.
 

Detailed Description

Handle table and batched decode orchestrator for branch management.

Provides two concerns:

Slot management — A pool of BranchState slots addressed by opaque handles with generation counters for ABA prevention. Slot 0 is permanently reserved (handle 0 = INVALID_HANDLE). Auto-grows by doubling up to 65535 slots. Methods: allocate(), release(), get().

Batched decode — Orchestrates multi-branch GPU dispatches that amortize llama_decode() overhead across N branches. Each method validates handles, builds the appropriate decode primitive's input, dispatches, captures logits into per-branch snapshots, and advances positions atomically. Methods: decode_each(), decode_scatter().

Batched decode methods vs free-function decode:

Method Tokens/branch Chunking Logit capture
decode_each() 1 No (1 call) Per-branch
decode_scatter() Variable Auto Per-branch
branch::step() 1 No Single branch
Warning
n_seq_max constraint: Each live branch consumes one KV cache sequence ID (llama_seq_id) managed by kv::tenancy. Call init_tenancy(ctx) after context creation to set the ceiling. The hard limit is llama_n_seq_max(ctx) (typically 256). allocate() acquires both a slot and a lease atomically; release()/drain() return both resources symmetrically.
Thread safety: External synchronization required. The store holds no lock: callers must not touch a branch, or the shared context, while native work on it is in flight.
See also
branch::create() to initialize a branch in this store
branch::fork() to clone a branch into a new sequence
branch::prune() / branch::destroy() for teardown

Definition at line 490 of file branch.hpp.

Constructor & Destructor Documentation

◆ BranchStore()

lloyal::branch::BranchStore::BranchStore ( size_t  initial_capacity = 16)
inlineexplicit

Construct a branch store with initial slot capacity.

Parameters
initial_capacityNumber of slots to pre-allocate (minimum 2)

Definition at line 496 of file branch.hpp.

◆ ~BranchStore()

lloyal::branch::BranchStore::~BranchStore ( )
inline

Destructor — frees CPU resources.

drain() must be called first while the llama_context is still alive.

Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 515 of file branch.hpp.

Member Function Documentation

◆ add_cells_used()

void lloyal::branch::BranchStore::add_cells_used ( uint32_t  n)
inline

Increment cells_used counter (for standalone prefill/step outside BranchStore methods)

Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 767 of file branch.hpp.

◆ add_model_surprisal()

void lloyal::branch::BranchStore::add_model_surprisal ( MetricsHandle  h,
float  surprisal 
)
inline

Add model-level surprisal to a metrics tracker.

Parameters
hMetrics handle
surprisalSurprisal in nats
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 1035 of file branch.hpp.

◆ add_sampling_surprisal()

void lloyal::branch::BranchStore::add_sampling_surprisal ( MetricsHandle  h,
float  surprisal 
)
inline

Add sampling-level surprisal to a metrics tracker.

Parameters
hMetrics handle
surprisalSurprisal in nats
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 1049 of file branch.hpp.

◆ allocate()

Allocation lloyal::branch::BranchStore::allocate ( )
inline

Allocate a branch slot + KV lease atomically.

Acquires a seq_id from tenancy, then a slot from the freelist. If either fails, both are rolled back cleanly.

Returns
{handle, seq_id}, or {INVALID_HANDLE, -1} if exhausted
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 537 of file branch.hpp.

◆ available()

size_t lloyal::branch::BranchStore::available ( ) const
inline

Number of vacant seq_ids available for acquisition.

Returns
Count of seq_ids in the tenancy vacant pool
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 750 of file branch.hpp.

◆ children()

const std::vector< BranchHandle > & lloyal::branch::BranchStore::children ( BranchHandle  h) const
inline

Get a branch's child handles.

Parameters
hBranch handle
Returns
Reference to child handle vector (empty if leaf or invalid)
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 794 of file branch.hpp.

◆ clone_grammar()

GrammarHandle lloyal::branch::BranchStore::clone_grammar ( GrammarHandle  h)
inline

Clone a grammar (for fork)

Parameters
hSource grammar handle
Returns
New handle with cloned grammar, or 0 if source is invalid
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 966 of file branch.hpp.

◆ clone_metrics()

MetricsHandle lloyal::branch::BranchStore::clone_metrics ( MetricsHandle  h)
inline

Clone a metrics tracker (for fork)

Parameters
hSource metrics handle
Returns
New handle with cloned state, or 0 if source is invalid
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 1013 of file branch.hpp.

◆ clone_sampler()

SamplerChainHandle lloyal::branch::BranchStore::clone_sampler ( SamplerChainHandle  h)
inline

Clone a sampler chain (for fork)

Parameters
hSource sampler chain handle
Returns
New handle with cloned chain, or 0 if source is invalid
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 876 of file branch.hpp.

◆ create_grammar()

GrammarHandle lloyal::branch::BranchStore::create_grammar ( const llama_model *  model,
const char *  grammar_str,
const char *  root = "root" 
)
inline

Create a grammar sampler and register it.

Parameters
modelLlama model (for vocab)
grammar_strGBNF grammar string
rootRoot rule name (default "root")
Returns
Handle to the new grammar (never 0)
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 927 of file branch.hpp.

◆ create_grammar_lazy()

GrammarHandle lloyal::branch::BranchStore::create_grammar_lazy ( const llama_model *  model,
const char *  grammar_str,
const std::vector< std::string > &  trigger_patterns,
const std::vector< llama_token > &  trigger_tokens,
const char *  root = "root" 
)
inline

Create a lazy grammar (unconstrained until trigger fires)

Parameters
modelLlama model (for vocab)
grammar_strGBNF grammar string
trigger_patternsRegex patterns that activate the grammar
trigger_tokensToken IDs that activate the grammar
rootRoot rule name (default "root")
Returns
Handle to the new grammar, or 0 on failure
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 946 of file branch.hpp.

◆ create_metrics()

MetricsHandle lloyal::branch::BranchStore::create_metrics ( )
inline

Create a metrics tracker and register it.

Returns
Handle to the new tracker (never 0)
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 1002 of file branch.hpp.

◆ create_sampler()

template<SamplingParamsLike P>
SamplerChainHandle lloyal::branch::BranchStore::create_sampler ( const P &  params,
int32_t  n_vocab 
)
inline

Create a sampler chain and register it.

Parameters
paramsSampling parameters (any SamplingParamsLike type)
Returns
Handle to the new sampler chain (never 0)
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 861 of file branch.hpp.

◆ decode_each()

void lloyal::branch::BranchStore::decode_each ( std::span< const DecodeEachItem >  items)
inline

Decode one token per branch in a single GPU dispatch.

Packs N tokens (one per branch) into a single llama_batch and calls decode::each(), amortizing GPU dispatch overhead across all branches. After decode, captures logits from the batch into each branch's logits_snapshot and advances each branch's position by 1.

Note
Batch index mapping: item[i] in the batch corresponds to llama_get_logits_ith(ctx, i). This is a 1:1 mapping because decode::each places exactly one token per batch slot.
Uses an internal scratch buffer. Since BranchStore requires external synchronization (caller's mutex), no concurrent access is possible.
Parameters
itemsSpan of {handle, token} pairs (all handles must be valid)
Exceptions
std::runtime_errorif any handle is invalid, contexts don't match, or decode fails
See also
decode::each() for the underlying single-batch primitive
decode_scatter() for variable token counts per branch
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 1110 of file branch.hpp.

◆ decode_embd()

void lloyal::branch::BranchStore::decode_embd ( BranchHandle  handle,
const float *  rows,
int32_t  n_tokens,
int32_t  n_embd_inp,
llama_pos  n_pos,
const llama_pos *  pos,
int32_t  n_pos_per_embd,
bool  non_causal,
bool  want_logits 
)
inline

Decode embedding rows into ONE branch's KV (multimodal ingress)

The branch-level wrapper over decode::embd(): dispatches the rows into the branch's sequence and does the bookkeeping the token paths do for tokens — with the one multimodal difference: cells grow by n_tokens (every row is a KV cell) while position advances by n_pos (max(nx,ny) under M-RoPE; == n_tokens for plain-position models). The gap is tracked as embedding-row slack so release()/retainOnly() recover the true cell count.

Rows are an interior prefix: no logits are captured unless want_logits (the rows-terminal prefill), in which case the final row's logits land in logits_snapshot like a token prefill's would.

Always its own dispatch: a legacy llama_batch carries rows or tokens, not both. A multimodal prefill goes through decode_segments, which places text and rows in order through the rail, with the same books.

Parameters
handleBranch to decode into (must be valid + leased)
rowsEmbedding rows, n_tokens x n_embd_inp floats
n_tokensNumber of rows (cells added)
n_embd_inpRow width — llama_model_n_embd_inp(model)
n_posPosition advance (max(nx,ny) under M-RoPE)
posSection-major positions, n_tokens * n_pos_per_embd
n_pos_per_embd1 (plain) or 4 (M-RoPE)
non_causalBracket the decode in non-causal attention
want_logitsCapture the final row's logits (rows-terminal)
Exceptions
std::runtime_errorif the handle is invalid or decode fails

Handling a failed prefill

This is NOT atomic. Rows chunk by n_batch — an image larger than the batch is the normal case, not an edge — so a failure on a later chunk leaves earlier ones committed while the counters here never move.

There is no rollback to reach for. Rewinding the committed rows means a partial-range seq_rm, which cannot restore a recurrent carrier (see kv::remove_range's warning). Attempting it rolls attention back, leaves the carrier folded, and looks like it worked — worse than not trying.

In order of preference:

  1. PREVENT. Exhausting the KV is the likeliest cause and the only one knowable in advance. A source reports its cost before anything decodes — see decode::SegmentSource::cells() — so admit or refuse the prefill against your own budget instead of discovering it midway.
  2. CONTAIN. If it throws anyway the branch is poisoned: prune it. Its OWN accounting is still consistent for that prune, because neither position nor cells_used_ advanced — release() subtracts exactly what the branch legitimately owned, and whole-sequence eviction reclaims the orphaned rows. Siblings are untouched.
  3. RECOVER. Replay the content onto a fresh branch. A branch stores its position and never what was decoded into it, so the content comes from you — the same reason replay is the portable correction at all: it re-runs the folds rather than trying to undo them.
See also
kv::remove_range() for why rewinding is not an option
decode::embd() for the underlying primitive
decode_scatter() for the token rail
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 1340 of file branch.hpp.

◆ decode_scatter()

void lloyal::branch::BranchStore::decode_scatter ( std::span< const DecodeScatterItem >  items)
inline

Decode variable token counts per branch with auto-chunking.

Two-pass algorithm:

Pass 1 — Build chunks: Greedily bin-packs items into chunks up to llama_n_batch(ctx) tokens. Oversized items (tokens.size() > n_batch) get their own chunk and are dispatched via decode::many(). Zero-length items are silently skipped.

Pass 2 — Dispatch: Iterates chunks, dispatching normal chunks via decode::scatter() and oversized chunks via decode::many(). Captures logits into per-branch snapshots and advances positions.

Note
Uses an internal scratch buffer. Since BranchStore requires external synchronization (caller's mutex), no concurrent access is possible.

The books move as each chunk lands, so a failure on a later chunk leaves the landed branches consistent (position and cells agree) and the rest untouched; the error's partial says which case the caller is in.

Parameters
itemsSpan of {handle, tokens} pairs (all handles must be valid)
Exceptions
std::runtime_errorif any handle is invalid or contexts don't match
decode::DecodeErrorif a chunk fails — partial set when an earlier chunk landed
See also
decode::scatter() for the underlying single-batch primitive
decode::many() for the oversized-item fallback
decode_each() for the simpler one-token-per-branch variant
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 1189 of file branch.hpp.

◆ decode_segments()

DecodeSegmentsResult lloyal::branch::BranchStore::decode_segments ( BranchHandle  handle,
decode::SegmentSource &  source,
const std::function< void(const decode::SegmentProgress &)> &  on_progress = {} 
)
inline

Prefill a heterogeneous segment sequence into ONE branch.

The branch's side of decode::segments, the rail that places the stream: it starts at the branch's position, lands in the branch's sequence, chunks rows by the branch's n_batch, and moves the books (position, cells, slack, logits) as each segment lands, through the same helpers the token and embedding rails use. Positions come from the branch's own state and never leave it.

Only the FINAL segment's logits survive: every llama_decode resets the output buffer, so an interior segment's snapshot is immediately dead. Every TEXT segment computes logits and is captured, the interior captures simply overwritten. EMBD segments request output explicitly, so only a trailing one does. Either way the branch ends holding the last segment's.

Segments are requested and dispatched strictly in order — see SegmentSource's in-order contract; a source may reuse its row buffer between at() calls. Every segment must be material: an empty one is rejected, because terminality is positional and a trailing empty segment would leave the real last one without logits.

Warning
NOT atomic. Once the first segment is dispatched the branch has been mutated, so a later throw — from the source or from a decode — leaves it partially advanced. The branch is poisoned at that point: prune it and rebuild rather than continuing from it. A DecodeError from any segment after the first carries partial = true for that reason, whichever of its calls failed — the prefill is one operation to the caller.
Parameters
handleBranch to prefill (must be valid + leased)
sourceYields the segments; owns production, not placement
on_progressTold, as each segment of an input lands, how much of that input is in the KV and of how much (SegmentProgress). The prompt's own text reports nothing. Never called after a failure.
Returns
Cells added and position advance (they differ under M-RoPE)
Exceptions
std::runtime_errorif the handle is invalid or a decode fails
See also
decode::segments() for the rail
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 1430 of file branch.hpp.

◆ drain()

void lloyal::branch::BranchStore::drain ( )
inline

Explicit teardown — evict all leases while context is alive.

Must be called before llama_free(ctx). Idempotent. Terminal — BranchStore is not reusable after drain(). freelist_ is not repopulated; call init_tenancy() on a fresh store if you need a new cycle. After drain(), allocate() returns {INVALID_HANDLE, NO_LEASE}.

Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 618 of file branch.hpp.

◆ fast_forward()

void lloyal::branch::BranchStore::fast_forward ( BranchHandle  parent,
BranchHandle  child 
)
inline

Fast-forward parent to child: the child's state becomes the parent's.

git's merge --ff-only. With fork() and prune() it gives any branch a checkpoint it can keep or discard while the rest of the tree runs on: fork, work on the fork, then fast-forward the parent to it or prune it.

The parent keeps its identity (handle, parent, children, fork_head, n_batch, steer_fn) and takes everything that follows the child's token trajectory: its sequence and KV, position, image slack, logits snapshot, sampler chain and parameters, grammar and grammar order, last sample, metrics and logit bias. A grammar holds its rules and its parser position in one sampler, and the chain holds its parameters with the penalty window and PRNG, so they move whole: configuration set on the child after the fork comes with it. The child's steer_fn is dropped with the child.

No cells move. The parent's former sequence is evicted whole, which is safe on recurrent layers; siblings still sharing its cells keep them. The parent's former sampler, grammar and metrics are freed with the child's slot, and cells_used is unchanged: the child's cells were counted when they were decoded, and the parent's are all shared with the child.

No native work may be in flight on the context while it runs, on these branches or any other: evicting the parent's former sequence is a KV operation on the shared context (external synchronization, as for every BranchStore operation).

Exceptions
std::runtime_error,changingnothing, unless the child was forked from this parent, the parent has neither decoded nor changed since, the child has no children and is not poisoned, and both hold a lease
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 697 of file branch.hpp.

◆ fork_head()

llama_pos lloyal::branch::BranchStore::fork_head ( BranchHandle  h) const
inline

Get a branch's fork head (parent position at fork time)

Parameters
hBranch handle
Returns
Fork head position (0 for root branches or invalid handles)
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 784 of file branch.hpp.

◆ free_grammar()

void lloyal::branch::BranchStore::free_grammar ( GrammarHandle  h)
inline

Free a grammar.

Parameters
hHandle to free (0 is a safe no-op)
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 981 of file branch.hpp.

◆ free_metrics()

void lloyal::branch::BranchStore::free_metrics ( MetricsHandle  h)
inline

Free a metrics tracker.

Parameters
hHandle to free (0 is a safe no-op)
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 1026 of file branch.hpp.

◆ free_sampler()

void lloyal::branch::BranchStore::free_sampler ( SamplerChainHandle  h)
inline

Free a sampler chain.

Parameters
hHandle to free (0 is a safe no-op)
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 892 of file branch.hpp.

◆ get() [1/2]

BranchState * lloyal::branch::BranchStore::get ( BranchHandle  handle)
inline

Look up branch state by handle.

Validates the handle's index, generation, and in-use flag. Slot 0 always returns nullptr (reserved for INVALID_HANDLE).

Parameters
handleBranch handle to look up
Returns
Pointer to BranchState, or nullptr if handle is invalid/stale
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 829 of file branch.hpp.

◆ get() [2/2]

const BranchState * lloyal::branch::BranchStore::get ( BranchHandle  handle) const
inline

Look up branch state by handle.

Validates the handle's index, generation, and in-use flag. Slot 0 always returns nullptr (reserved for INVALID_HANDLE).

Parameters
handleBranch handle to look up
Returns
Pointer to BranchState, or nullptr if handle is invalid/stale

Definition at line 849 of file branch.hpp.

◆ get_grammar_sampler()

llama_sampler * lloyal::branch::BranchStore::get_grammar_sampler ( GrammarHandle  h) const
inline

Dereference a grammar handle (non-owning)

Parameters
hGrammar handle
Returns
Pointer to the grammar sampler, or nullptr if invalid
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 990 of file branch.hpp.

◆ get_model_ppl()

float lloyal::branch::BranchStore::get_model_ppl ( MetricsHandle  h) const
inline

Get model-level perplexity from a metrics tracker.

Parameters
hMetrics handle
Returns
exp(average surprisal), INFINITY if no samples or invalid
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 1063 of file branch.hpp.

◆ get_sampler_chain()

llama_sampler * lloyal::branch::BranchStore::get_sampler_chain ( SamplerChainHandle  h) const
inline

Dereference a sampler chain handle (non-owning)

Parameters
hSampler chain handle
Returns
Pointer to the chain, or nullptr if invalid
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 901 of file branch.hpp.

◆ get_sampling_ppl()

float lloyal::branch::BranchStore::get_sampling_ppl ( MetricsHandle  h) const
inline

Get sampling-level perplexity from a metrics tracker.

Parameters
hMetrics handle
Returns
exp(average surprisal), INFINITY if no samples or invalid
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 1077 of file branch.hpp.

◆ init_tenancy()

void lloyal::branch::BranchStore::init_tenancy ( llama_context *  ctx)
inline

Initialize KV tenancy after context creation.

Parameters
ctxLlama context (must outlive BranchStore or call drain() first)
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 605 of file branch.hpp.

◆ isActive()

bool lloyal::branch::BranchStore::isActive ( BranchHandle  h) const
inline

Test whether a branch holds a KV lease.

Parameters
hBranch handle
Returns
true if seq_id != NO_LEASE, false if inactive or handle is invalid
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 815 of file branch.hpp.

◆ isLeaf()

bool lloyal::branch::BranchStore::isLeaf ( BranchHandle  h) const
inline

Test whether a branch is a leaf (no children)

Parameters
hBranch handle
Returns
true if branch has no children or handle is invalid
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 805 of file branch.hpp.

◆ kv_pressure()

KvPressure lloyal::branch::BranchStore::kv_pressure ( ) const
inline

KV cache pressure snapshot — O(1), no tree walking.

cells_used tracks unique KV cells per branch. Incremented on decode_each/decode_scatter, decremented on release (position - fork_head), reset on drain/retainOnly/init_tenancy.

Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 759 of file branch.hpp.

◆ merge_logits()

void lloyal::branch::BranchStore::merge_logits ( BranchHandle  dst_handle,
std::span< const BranchHandle >  expert_handles,
float  alpha 
)
inline

Merge experts' logits_snapshot into dst's logits_snapshot.

Accumulates additively (in log-probability space): dst.logits_snapshot[t] += alpha * sum_i(experts[i].logits_snapshot[t])

Mutates dst in place. After this call, sample/produce on dst draws from the combined distribution via dst's existing sampler chain.

Backend-agnostic: operates purely on cached logits buffers, no KV ops, no GPU dispatch. Works identically for transformer and recurrent backends.

Inspired by DExperts-style contrastive decoding (Liu et al., 2021 — https://arxiv.org/abs/2105.03023). Here the experts are different KV states of the SAME model rather than separate models: their live logits_snapshot at each step reflects their own KV history, shaping dst's next-token choice. A negative alpha makes an anti-expert.

Parameters
dst_handleDestination branch (must have captured logits)
expert_handlesSpan of expert branches (all must have captured logits)
alphaExpert weight (additive in log space)
Exceptions
std::runtime_errorif any handle invalid, logits not captured, or n_vocab mismatch across branches; a refusal changes nothing

Definition at line 1504 of file branch.hpp.

◆ parent()

BranchHandle lloyal::branch::BranchStore::parent ( BranchHandle  h) const
inline

Get a branch's parent handle.

Parameters
hBranch handle
Returns
Parent handle, or INVALID_HANDLE if root or handle is invalid
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 774 of file branch.hpp.

◆ release()

void lloyal::branch::BranchStore::release ( BranchHandle  handle)
inline

Release a branch slot + evict its KV lease.

Removes parent→child edge, evicts the seq_id (stripping KV tags), frees CPU resources, and returns the slot to the freelist.

Parameters
handleBranch handle to release (INVALID_HANDLE is a safe no-op)
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 561 of file branch.hpp.

◆ retainOnly()

void lloyal::branch::BranchStore::retainOnly ( BranchHandle  winner)
inline

Keep only the winner — nuclear KV + CPU cleanup.

Calls seq_keep(winner_seq) for a single KV pass, then releases all other slots (CPU only — KV already stripped by seq_keep).

Parameters
winnerHandle to the branch to retain (must be valid + leased)
Exceptions
std::runtime_errorif winner is invalid or has no lease
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 640 of file branch.hpp.

◆ sampler_has_dist()

bool lloyal::branch::BranchStore::sampler_has_dist ( SamplerChainHandle  h) const
inline

Check if a sampler chain ends with dist (stochastic) or greedy.

Parameters
hSampler chain handle
Returns
true if chain has dist sampler, false if greedy or invalid
Examples
/home/runner/work/liblloyal/liblloyal/include/lloyal/branch.hpp.

Definition at line 912 of file branch.hpp.


The documentation for this class was generated from the following file: