Class DeltaNetStatePool
- All Implemented Interfaces:
AutoCloseable
Recurrent state is typically float32 (fused CUDA kernel / stable in-place updates).
Conv left-context must match the compute dtype (bf16/fp16) so decode
concat(convState, hidden) does not promote activations to float and
break later bf16 linear layers.
Multi-request continuous batching assigns each requestId a stable
home row. activateStep(int...) packs those rows into [0, B) for the
mixer; scatterActive() writes them back after the forward.
-
Constructor Summary
ConstructorsConstructorDescriptionDeltaNetStatePool(int numLinearLayers, int numVHeads, int keyHeadDim, int valueHeadDim, int convDim, int convKernel, int maxBatchSize, Device device, ScalarType dtype) Constructor using the same dtype for recurrent and conv buffers (tests).DeltaNetStatePool(int numLinearLayers, int numVHeads, int keyHeadDim, int valueHeadDim, int convDim, int convKernel, int maxBatchSize, Device device, ScalarType recurrentDtype, ScalarType convDtype) Constructor with separate recurrent / conv dtypes. -
Method Summary
Modifier and TypeMethodDescriptionvoidactivateStep(int... requestIds) Packs bound request rows into working slots[0, B)for a forward.activeConv(int linearLayerId) Conv rows packed byactivateStep(int...)into[0, boundBatch).activeRecurrent(int linearLayerId) Recurrent rows packed byactivateStep(int...)into[0, boundBatch).intbindRequest(int requestId) Binds a stable home row forrequestIdand zeros it.intReturns the bound batch size.intReturns the number of multi-request bindings.voidclose()conv(int linearLayerId) Returns the conv state buffer for a linear-attention layer.booleanensureSpeculativeCheckpointRange(int firstSlot, int lastSlot) Allocates checkpoint slotsfirstSlot..lastSlot(inclusive) only, formax(1, boundBatch)rows.booleanensureSpeculativeCheckpointRange(int firstSlot, int lastSlot, int rows) Allocates checkpoint slotsfirstSlot..lastSlotfor an explicit number of rows, so the memory can be reserved at startup (before the KV pool is sized) instead of being grown on demand once the GPU is nearly full.booleanensureSpeculativeCheckpoints(int numSlots) EnsuresnumSlotsmid-verify checkpoint buffers sized for the currently activated batch (boundBatch), not the full poolmaxBatchSize.booleanhasSpeculativeCheckpoints(int slots, int rows) Whether per-step checkpoints forslotsslots androwsrows are allocated.booleanhasSpeculativeRange(int firstSlot, int lastSlot, int rows) Whether checkpoint slotsfirstSlot..lastSlotare stored for at leastrowsrows.intReturns the linear-attention layer count.recurrent(int linearLayerId) Returns the recurrent state buffer for a linear-attention layer.voidReleases speculative checkpoint buffers (call after a verify round when GPU headroom is tight).voidreset(int batchSize) Zeros all states and records the active batch size (legacy exclusive generate).voidrestoreCheckpoint(int slot) Restores active working rows from checkpointslot.voidrestoreCheckpointPerRow(int[] slots) Restores each active rowifrom its own checkpoint slotslots[i]— the batched-cohort counterpart ofrestoreCheckpoint(int), which restores every active row from the same slot.voidsaveCheckpoint(int slot) Copies active working rows[0, boundBatch)into checkpointslot.voidsaveCheckpointForLayer(int slot, int layerId) Copies active working rows[0, boundBatch)for a single linear-attention layer into checkpointslot.voidWrites working slots[0, B)back to each request's home row.voidsetVerifyWindowActive(boolean active) Sets whether the primary MTP verify-window forward is in flight.longspeculativeCheckpointBytes(int numSlots, int rows) Device bytes of the speculative checkpoint buffers fornumSlotsslots ofrowsrows each (all linear layers, recurrent plus conv state).longspeculativeCheckpointGrowthBytes(int numSlots, int rows) Additional device bytesensureSpeculativeCheckpoints(int)would have to allocate fornumSlotsxmax(1, rows)(0 when the existing buffers already suffice).longspeculativeCheckpointGrowthBytes(int firstSlot, int lastSlot, int rows) Additional device bytesensureSpeculativeCheckpointRange(int, int)would have to allocate for slotsfirstSlot..lastSlotofmax(1, rows)rows (0 when already sufficient).speculativeConvSlot(int slot, int layerId) Returns checkpointslot's full conv tensor for a linear layer ([rows, C, K-1]), ornullwhen absent.speculativeRecurrentSlot(int slot, int layerId) Returns checkpointslot's full recurrent tensor for a linear layer ([rows, H, K, V], float, contiguous), ornullwhen absent.voidunbind()Clears the active-request binding after exclusive generate finishes.voidunbindRequest(int requestId) Releases the home row forrequestId.booleanReturns whether the primary MTP verify-window forward is in flight.voidwithPreservedActive(Runnable action) Runsactionwithout permanently mutating the active DeltaNet working rows.
-
Constructor Details
-
DeltaNetStatePool
public DeltaNetStatePool(int numLinearLayers, int numVHeads, int keyHeadDim, int valueHeadDim, int convDim, int convKernel, int maxBatchSize, Device device, ScalarType dtype) Constructor using the same dtype for recurrent and conv buffers (tests).- Parameters:
numLinearLayers- number of linear-attention layers.numVHeads- number of value heads.keyHeadDim- key head dimension.valueHeadDim- value head dimension.convDim- causal conv channel dimension.convKernel- causal conv kernel size.maxBatchSize- maximum concurrent home rows.device- storage device.dtype- dtype for both recurrent and conv buffers.
-
DeltaNetStatePool
public DeltaNetStatePool(int numLinearLayers, int numVHeads, int keyHeadDim, int valueHeadDim, int convDim, int convKernel, int maxBatchSize, Device device, ScalarType recurrentDtype, ScalarType convDtype) Constructor with separate recurrent / conv dtypes.- Parameters:
numLinearLayers- number of linear-attention layers.numVHeads- number of value heads.keyHeadDim- key head dimension.valueHeadDim- value head dimension.convDim- causal conv channel dimension.convKernel- causal conv kernel size.maxBatchSize- maximum concurrent home rows.device- storage device.recurrentDtype- dtype for recurrent state buffers.convDtype- dtype for conv state buffers.
-
-
Method Details
-
reset
public void reset(int batchSize) Zeros all states and records the active batch size (legacy exclusive generate).- Parameters:
batchSize- active batch size.
-
bindRequest
public int bindRequest(int requestId) Binds a stable home row forrequestIdand zeros it.- Parameters:
requestId- id aligned withKvCachePool.bindRequest(int[], int).- Returns:
- home row index.
-
unbindRequest
public void unbindRequest(int requestId) Releases the home row forrequestId.- Parameters:
requestId- previously bound id.
-
activateStep
public void activateStep(int... requestIds) Packs bound request rows into working slots[0, B)for a forward.Working slots are the same storage as the first
Bhome rows, so packing has to be careful in two ways. First, all sources are read before any is written (a sequential home-to-slot copy corrupts the cohort itself when homes are not in ascending order, e.g. once freed rows have been reused by later requests). Second, any live request outside the cohort whose home row lies in[0, B)is stashed and put back byscatterActive(), so a forward over one cohort never disturbs another's state (a speculating group and a plain-decode group alternate within one engine tick, for example). When the cohort already occupies rows0..B-1in order nothing is copied.- Parameters:
requestIds- bound request ids (order = batch).
-
setVerifyWindowActive
public void setVerifyWindowActive(boolean active) Sets whether the primary MTP verify-window forward is in flight.- Parameters:
active-truearound the verify-window forward only.
-
verifyWindowActive
public boolean verifyWindowActive()Returns whether the primary MTP verify-window forward is in flight.- Returns:
truewhenGatedDeltaNetshould run its per-position verify loop instead of the batchedS>1path.
-
scatterActive
public void scatterActive()Writes working slots[0, B)back to each request's home row. Call after every forward that usedactivateStep(int...). -
withPreservedActive
Runsactionwithout permanently mutating the active DeltaNet working rows.Used for CUDA graph prefetch forwards that share the current
activateStep(int...)packing.- Parameters:
action- work to run while active rows are preserved.
-
speculativeCheckpointBytes
public long speculativeCheckpointBytes(int numSlots, int rows) Device bytes of the speculative checkpoint buffers fornumSlotsslots ofrowsrows each (all linear layers, recurrent plus conv state).- Parameters:
numSlots- checkpoint slots.rows- batch rows per slot.- Returns:
- bytes the buffers occupy on this pool's device.
-
speculativeCheckpointGrowthBytes
public long speculativeCheckpointGrowthBytes(int numSlots, int rows) Additional device bytesensureSpeculativeCheckpoints(int)would have to allocate fornumSlotsxmax(1, rows)(0 when the existing buffers already suffice).- Parameters:
numSlots- checkpoint slots required.rows- batch rows required.- Returns:
- extra bytes needed.
-
speculativeCheckpointGrowthBytes
public long speculativeCheckpointGrowthBytes(int firstSlot, int lastSlot, int rows) Additional device bytesensureSpeculativeCheckpointRange(int, int)would have to allocate for slotsfirstSlot..lastSlotofmax(1, rows)rows (0 when already sufficient).- Parameters:
firstSlot- first slot required.lastSlot- last slot required.rows- batch rows required.- Returns:
- extra bytes needed.
-
ensureSpeculativeCheckpoints
public boolean ensureSpeculativeCheckpoints(int numSlots) EnsuresnumSlotsmid-verify checkpoint buffers sized for the currently activated batch (boundBatch), not the full poolmaxBatchSize. Full-pool sizing OOMs under serving configs.Growth-only: never reallocates smaller for a later, smaller
boundBatch(the early-return below already guarantees this), since a shrink would be pointless — the real reason growth matters is that any verify CUDA graph already captured against the old, smaller buffers becomes invalid the moment this reallocates (replay would then write into freed memory) — see thetrue-return contract below.- Parameters:
numSlots- checkpoint slots (N+1forNdraft tokens).- Returns:
trueif this call reallocated (the caller must then invalidate any captured verify CUDA graph viaQwenModel.invalidateVerifyCudaGraphs()before it can be replayed again).
-
ensureSpeculativeCheckpointRange
public boolean ensureSpeculativeCheckpointRange(int firstSlot, int lastSlot) Allocates checkpoint slotsfirstSlot..lastSlot(inclusive) only, formax(1, boundBatch)rows. Slot numbers keep their meaning ("state after window positionslot-1", slot 0 = pre-window), but slots outside the range have no storage: a save to one is a no-op and a restore from one is an error. In checkpoint-replay mode only slots1..nare ever restored from (slot 0 is never read, and the last slot equals the working state), so allocating just those cuts the memory by2/(n+2).- Parameters:
firstSlot- first slot to store.lastSlot- last slot to store.- Returns:
trueif this call reallocated (seeensureSpeculativeCheckpoints(int)).
-
ensureSpeculativeCheckpointRange
public boolean ensureSpeculativeCheckpointRange(int firstSlot, int lastSlot, int rows) Allocates checkpoint slotsfirstSlot..lastSlotfor an explicit number of rows, so the memory can be reserved at startup (before the KV pool is sized) instead of being grown on demand once the GPU is nearly full.- Parameters:
firstSlot- first slot to store.lastSlot- last slot to store.rows- batch rows to provision.- Returns:
trueif this call reallocated.
-
hasSpeculativeRange
public boolean hasSpeculativeRange(int firstSlot, int lastSlot, int rows) Whether checkpoint slotsfirstSlot..lastSlotare stored for at leastrowsrows.- Parameters:
firstSlot- first checkpoint slot of the range (inclusive).lastSlot- last checkpoint slot of the range (inclusive).rows- minimum number of rows the checkpoints must cover.- Returns:
trueif the range is fully stored with at leastrowsrows.
-
releaseSpeculativeCheckpoints
public void releaseSpeculativeCheckpoints()Releases speculative checkpoint buffers (call after a verify round when GPU headroom is tight). -
saveCheckpoint
public void saveCheckpoint(int slot) Copies active working rows[0, boundBatch)into checkpointslot.- Parameters:
slot- checkpoint index (0 .. numSlots-1).
-
restoreCheckpoint
public void restoreCheckpoint(int slot) Restores active working rows from checkpointslot.- Parameters:
slot- checkpoint index (0 .. numSlots-1).
-
restoreCheckpointPerRow
public void restoreCheckpointPerRow(int[] slots) Restores each active rowifrom its own checkpoint slotslots[i]— the batched-cohort counterpart ofrestoreCheckpoint(int), which restores every active row from the same slot. Needed when concurrent requests verified together in one round accept different numbers of draft tokens.- Parameters:
slots- checkpoint slot per active row (lengthboundBatch).
-
speculativeRecurrentSlot
Returns checkpointslot's full recurrent tensor for a linear layer ([rows, H, K, V], float, contiguous), ornullwhen absent.- Parameters:
slot- checkpoint index.layerId- ordinal among linear-attention layers.- Returns:
- the checkpoint tensor (owned by the pool; do not close), or
null.
-
speculativeConvSlot
Returns checkpointslot's full conv tensor for a linear layer ([rows, C, K-1]), ornullwhen absent.- Parameters:
slot- checkpoint index.layerId- ordinal among linear-attention layers.- Returns:
- the checkpoint tensor (owned by the pool; do not close), or
null.
-
hasSpeculativeCheckpoints
public boolean hasSpeculativeCheckpoints(int slots, int rows) Whether per-step checkpoints forslotsslots androwsrows are allocated.- Parameters:
slots- number of checkpoint slots to check.rows- minimum number of rows the checkpoints must cover.- Returns:
trueif checkpoints forslotsslots androwsrows are allocated.
-
saveCheckpointForLayer
public void saveCheckpointForLayer(int slot, int layerId) Copies active working rows[0, boundBatch)for a single linear-attention layer into checkpointslot.Used by the verify-window per-position loop:
QwenModel's layer stack is depth-sequential, so each layer's own forward (including its internal per-position loop) finishes before the next layer starts. A whole-pool save mid-loop would capture sibling layers' stale state; this saves only the layer that just finished its own positiont.- Parameters:
slot- checkpoint index (0 .. numSlots-1).layerId- ordinal among linear-attention layers.
-
unbind
public void unbind()Clears the active-request binding after exclusive generate finishes. -
boundBatch
public int boundBatch()Returns the bound batch size.- Returns:
- bound batch size, or
0if unbound.
-
boundRequestCount
public int boundRequestCount()Returns the number of multi-request bindings.- Returns:
- number of multi-request bindings.
-
recurrent
Returns the recurrent state buffer for a linear-attention layer.- Parameters:
linearLayerId- ordinal among linear-attention layers.- Returns:
- recurrent state
[maxBatch, V, Kdim, Vdim](firstboundBatchrows active).
-
activeRecurrent
Recurrent rows packed byactivateStep(int...)into[0, boundBatch).Mixer forwards must use this (not
recurrent) so batch matmul seesstate.shape()[0] == query.shape()[0].- Parameters:
linearLayerId- ordinal among linear-attention layers.- Returns:
- view
[boundBatch, V, Kdim, Vdim]into the pool buffer.
-
activeConv
Conv rows packed byactivateStep(int...)into[0, boundBatch).- Parameters:
linearLayerId- ordinal among linear-attention layers.- Returns:
- view
[boundBatch, C, K-1], ornullif unused.
-
conv
Returns the conv state buffer for a linear-attention layer.- Parameters:
linearLayerId- ordinal among linear-attention layers.- Returns:
- conv state
[maxBatch, C, K-1], ornullif unused.
-
numLinearLayers
public int numLinearLayers()Returns the linear-attention layer count.- Returns:
- linear layer count.
-
close
public void close()- Specified by:
closein interfaceAutoCloseable
-