#[non_exhaustive]pub struct BlockPagedLayout {
pub page_size: u32,
pub num_pages: u64,
pub paged_axis: u32,
pub num_seqs: u32,
pub kv_role: KvRole,
pub layer_index: Option<u32>,
pub block_table_index_type: BlockTableIndexType,
}Expand description
Descriptor for the block-paged indirect layout.
Block-paged stores a KV-cache tensor whose paged axis is divided into fixed-size pages drawn from a shared page pool, with a block table mapping each logical page position to a physical page ID. It is the interchange form of a PagedAttention KV cache.
This layout is defined only for rank-3 tensors in this version of the
specification: [total_tokens, num_heads, head_dim].
Three buffers are always required:
| Buffer | Name | Description |
|---|---|---|
| 0 | page_pool | Flat pool of fixed-size pages. |
| 1 | block_table | Concatenated per-sequence page-ID lists. |
| 2 | seq_ptr | CSR-style offset array into block_table. |
When the tensor carries quantization parameters, additional buffers appear
at indices 3 and above per docs/spec/quantization.md § Buffer Table Placement Rules.
See docs/spec/layouts/block-paged.md for the full normative definition.
§Examples
use hurray_core::layout::{BlockPagedLayout, BlockTableIndexType, KvRole, LayoutDescriptor};
let layout = BlockPagedLayout::new(16, 128, 0, 4, KvRole::Key, Some(3), BlockTableIndexType::U32);
assert_eq!(layout.page_size, 16);
assert_eq!(layout.num_pages, 128);
assert_eq!(layout.num_seqs, 4);
assert_eq!(layout.layer_index, Some(3));
let desc = LayoutDescriptor::BlockPaged(layout);
assert_eq!(desc.tag(), 0x0A);
assert_eq!(desc.buffer_count().map(|n| n.get()), Some(3));Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.page_size: u32Tokens per page. MUST be >= 1.
Common values are 16 and 32 (matching vLLM’s default block_size).
num_pages: u64Number of physical pages in page_pool.
paged_axis: u32The axis subdivided into pages. MUST be 0 in this spec version.
Kept as a field rather than a constant so that the wire format remains forward-compatible if a future spec version adds non-zero paged axes.
num_seqs: u32Number of sequences in the batch. MAY be 0 for an empty batch.
kv_role: KvRoleKV-cache role for this tensor (key, value, or fused/generic).
layer_index: Option<u32>Transformer layer index, or None if the tensor is not layer-scoped.
Wire value 0xFFFFFFFF maps to None; all other values map to Some(n).
block_table_index_type: BlockTableIndexTypeElement type for both the block_table (buffer 1) and seq_ptr (buffer 2).
U32 is the default and addresses up to 4 billion pages.
U64 is required for larger pools.
Implementations§
Source§impl BlockPagedLayout
impl BlockPagedLayout
Sourcepub fn new(
page_size: u32,
num_pages: u64,
paged_axis: u32,
num_seqs: u32,
kv_role: KvRole,
layer_index: Option<u32>,
block_table_index_type: BlockTableIndexType,
) -> Self
pub fn new( page_size: u32, num_pages: u64, paged_axis: u32, num_seqs: u32, kv_role: KvRole, layer_index: Option<u32>, block_table_index_type: BlockTableIndexType, ) -> Self
Creates a new BlockPagedLayout.
§Arguments
page_size— tokens per page (MUST be validated >= 1 later viavalidate_against_shape).num_pages— number of physical pages in the pool.paged_axis— the axis subdivided into pages (MUST be 0 in this version).num_seqs— number of sequences in the batch.kv_role— KV-cache role for this tensor.layer_index— transformer layer index (None= not layer-scoped).block_table_index_type— element type forblock_tableandseq_ptrbuffers.
This constructor does not validate page_size >= 1 or paged_axis == 0 because
the tensor shape is not available at construction time. Call
[LayoutDescriptor::validate_against_shape] to perform all invariant checks
once the shape is known.
§Examples
use hurray_core::layout::{BlockPagedLayout, BlockTableIndexType, KvRole};
// Layer-3 key cache: page_size=16, 64 pages, 2 sequences, uint32 indices.
let layout = BlockPagedLayout::new(
16, 64, 0, 2,
KvRole::Key,
Some(3),
BlockTableIndexType::U32,
);
assert_eq!(layout.page_size, 16);
assert_eq!(layout.layer_index, Some(3));Sourcepub fn validate_quantization_compatibility(
&self,
scheme_tag: u8,
quant_axis: u32,
quant_block_size: u32,
) -> Result<()>
pub fn validate_quantization_compatibility( &self, scheme_tag: u8, quant_axis: u32, quant_block_size: u32, ) -> Result<()>
Validates that a quantization scheme is compatible with this block-paged layout.
Per docs/spec/layouts/block-paged.md § Quantization Compatibility:
- Per-tensor (
scheme_tag = 0x01): always compatible. - Per-channel (
scheme_tag = 0x02): MUST NOT be applied on axis 0 (the paged / token axis).quant_axismust be 1 (num_heads) or 2 (head_dim). - Per-block-affine (
scheme_tag = 0x03):quant_axisMUST be 0 andquant_block_sizeMUST equalpage_size. - All other schemes: not validated here; returns
Ok(()).
Call this at the typed-quantization layer once you have a decoded
crate::QuantizationDescriptor. The raw-bytes descriptor layer cannot
perform this check.
§Arguments
scheme_tag— thescheme_tagbyte from the quantization descriptor header.quant_axis— theaxisfield from the quantization descriptor (relevant for per-channel and per-block-affine).quant_block_size— theblock_sizefield from the per-block-affine descriptor (ignored for all other schemes).
§Errors
Returns crate::Error::InvalidQuantization if the scheme/layout combination
violates the spec rules above.
§Examples
use hurray_core::layout::{BlockPagedLayout, BlockTableIndexType, KvRole};
let layout = BlockPagedLayout::new(16, 64, 0, 2, KvRole::Key, Some(0), BlockTableIndexType::U32);
// Per-tensor (0x01) is always valid.
assert!(layout.validate_quantization_compatibility(0x01, 0, 0).is_ok());
// Per-channel on axis 1 (num_heads) is valid.
assert!(layout.validate_quantization_compatibility(0x02, 1, 0).is_ok());
// Per-channel on axis 0 (paged axis) is forbidden.
assert!(layout.validate_quantization_compatibility(0x02, 0, 0).is_err());
// Per-block-affine with axis=0 and block_size==page_size is valid.
assert!(layout.validate_quantization_compatibility(0x03, 0, 16).is_ok());
// Per-block-affine with block_size != page_size is forbidden.
assert!(layout.validate_quantization_compatibility(0x03, 0, 32).is_err());Trait Implementations§
Source§impl Clone for BlockPagedLayout
impl Clone for BlockPagedLayout
Source§fn clone(&self) -> BlockPagedLayout
fn clone(&self) -> BlockPagedLayout
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for BlockPagedLayout
impl Debug for BlockPagedLayout
impl Eq for BlockPagedLayout
Source§impl Hash for BlockPagedLayout
impl Hash for BlockPagedLayout
Source§impl PartialEq for BlockPagedLayout
impl PartialEq for BlockPagedLayout
Source§fn eq(&self, other: &BlockPagedLayout) -> bool
fn eq(&self, other: &BlockPagedLayout) -> bool
self and other values to be equal, and is used by ==.