Skip to content

Commit 495f30e

Browse files
authored
Document existing TurboQuant types (#8053)
## Summary Tracking issue: #7830 Adds a lot more documentation for the TurboQuant implementation (since in hindsight there are a lot of things that might not be obvious). ## Testing N/A Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
1 parent ae19fe7 commit 495f30e

5 files changed

Lines changed: 45 additions & 12 deletions

File tree

vortex-turboquant/src/scalar_fns/decode.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,21 @@ fn build_empty_vector(
203203
})
204204
}
205205

206+
/// Borrowed bundle of the per-array decode inputs passed to the typed inner loop.
207+
///
208+
/// Packaged as a struct rather than positional arguments because `decode_typed` runs through
209+
/// [`vortex_array::match_each_float_ptype!`] which expands once per supported element ptype.
210+
/// Each expansion takes the same set of inputs, and the struct keeps the call site short.
206211
struct DecodeInputs<'a> {
212+
/// TurboQuant metadata recovered from the input extension dtype.
207213
metadata: &'a TurboQuantMetadata,
214+
/// SORF transform reconstructed from `metadata.seed` and `metadata.num_rounds`.
208215
sorf_matrix: &'a SorfMatrix,
216+
/// Centroid codebook for `(padded_dim, bit_width)`, in f32.
209217
centroids: &'a [f32],
218+
/// Per-row stored L2 norm of the original input vector, in the element ptype.
210219
norms: &'a PrimitiveArray,
220+
/// Flat per-row centroid indices, `num_vectors * padded_dim` bytes.
211221
codes: &'a PrimitiveArray,
212222
}
213223

vortex-turboquant/src/sorf/splitmix64.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ const SPLITMIX64_MUL1: u64 = 0xBF58_476D_1CE4_E5B9;
1919
/// Second SplitMix64 mixing multiplier from the reference implementation.
2020
const SPLITMIX64_MUL2: u64 = 0x94D0_49BB_1331_11EB;
2121

22-
/// Frozen local SplitMix64 stream used to define SORF sign diagonals.
22+
/// Frozen local SplitMix64 stream used to define SORF sign diagonals. Bit-identical to the
23+
/// reference implementation linked at the module top, which makes the sign stream part of the
24+
/// encoding's wire contract.
2325
pub(crate) struct SplitMix64 {
2426
state: u64,
2527
}

vortex-turboquant/src/vector/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// SPDX-License-Identifier: Apache-2.0
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

4+
//! Vector-side helpers: normalization, quantization, and physical storage layout.
5+
46
pub(crate) mod normalize;
57
pub(crate) mod quantize;
68
pub(crate) mod storage;
@@ -9,6 +11,12 @@ use vortex_error::VortexResult;
911
use vortex_error::vortex_err;
1012

1113
/// Compute the padded SORF dimension for an original vector dimension.
14+
///
15+
/// The SORF transform requires a power-of-two width, so non-power-of-two input dimensions are
16+
/// padded with zeros up to the next power of two. The padded dimension is stored implicitly via
17+
/// [`TurboQuantMetadata::dimensions`](crate::TurboQuantMetadata) plus the codes child's
18+
/// `FixedSizeList` width and recovered at decode time via this function. Returns an error when
19+
/// the next power of two overflows the input integer type.
1220
pub(crate) fn tq_padded_dim(dimensions: u32) -> VortexResult<usize> {
1321
let padded_dim = dimensions
1422
.checked_next_power_of_two()

vortex-turboquant/src/vector/storage.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
//! converted into zero vectors. The code bytes for invalid rows are physical placeholders only; the
1818
//! field-level validity records that those rows were not quantized.
1919
//!
20-
//! Parsing treats the outer struct validity as authoritative. Child validity may be wider than the
21-
//! struct validity, for example after a generic mask only updates the struct validity, but each
22-
//! child must be valid wherever the struct row is valid.
20+
//! Parsing treats the outer struct validity as authoritative. Child validity may be wider than
21+
//! the struct validity (for example after a generic mask only updates the struct validity), but
22+
//! each child must be valid wherever the struct row is valid.
2323
2424
use vortex_array::ArrayRef;
2525
use vortex_array::ExecutionCtx;
@@ -48,14 +48,19 @@ pub(crate) const NORMS_FIELD: &str = "norms";
4848
/// Name of the stored quantized-code child.
4949
pub(crate) const CODES_FIELD: &str = "codes";
5050

51-
/// Parsed TurboQuant storage arrays.
52-
///
53-
/// We use this as a helper struct for working with a TurboQuant extension array.
51+
/// Executed storage children of a TurboQuant extension array plus the authoritative outer
52+
/// struct validity. Every child is row-aligned to `len` and every child's validity covers
53+
/// `vector_validity`.
5454
pub(crate) struct TurboQuantParsedStorage {
55+
/// Metadata recovered from the input extension dtype.
5556
pub(crate) metadata: TurboQuantMetadata,
57+
/// Authoritative row validity for the quantized vectors, taken from the outer struct.
5658
pub(crate) vector_validity: Validity,
59+
/// Per-row stored L2 norm of the original input vector, in `metadata.element_ptype`.
5760
pub(crate) norms: PrimitiveArray,
61+
/// Flat `u8` per-row centroid indices, `num_vectors * padded_dim` entries long.
5862
pub(crate) codes: PrimitiveArray,
63+
/// Row count.
5964
pub(crate) len: usize,
6065
}
6166

vortex-turboquant/src/vtable.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,20 @@ use crate::vector::storage::CODES_FIELD;
2626
use crate::vector::storage::NORMS_FIELD;
2727
use crate::vector::tq_padded_dim;
2828

29-
/// TurboQuant logical extension type.
29+
/// TurboQuant logical extension type. Per-array configuration lives in [`TurboQuantMetadata`].
3030
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
3131
pub struct TurboQuant;
3232

33-
/// Serialized metadata for a TurboQuant extension array.
33+
/// Serialized metadata for a TurboQuant extension array. The fields together suffice to
34+
/// reconstruct the SORF transform and centroid codebook at decode time.
3435
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3536
pub struct TurboQuantMetadata {
36-
/// Original vector element type and stored norm type.
37+
/// Original vector element ptype and stored row-norm ptype. Restricted to `f16` / `f32` /
38+
/// `f64`.
3739
pub element_ptype: PType,
38-
/// Original vector dimension before SORF padding.
40+
/// Original vector dimension before SORF padding to the next power of two.
3941
pub dimensions: u32,
40-
/// Bits per coordinate in the scalar quantizer codebook.
42+
/// Bits per coordinate in the scalar quantizer codebook (`1..=8`).
4143
pub bit_width: u8,
4244
/// Seed used to derive the deterministic SORF transform.
4345
pub seed: u64,
@@ -106,6 +108,8 @@ impl ExtVTable for TurboQuant {
106108
}
107109
}
108110

111+
/// Wire-format representation of [`TurboQuantMetadata`]. Field tags MUST NOT change once
112+
/// shipped; new fields must use unused tags and remain optional.
109113
#[derive(Clone, PartialEq, Message)]
110114
struct TurboQuantMetadataProto {
111115
#[prost(enumeration = "PType", tag = "1")]
@@ -158,6 +162,8 @@ pub(crate) fn tq_storage_dtype(
158162
))
159163
}
160164

165+
/// Validate [`TurboQuantMetadata`] invariants. Called on both serialize and deserialize so a
166+
/// corrupted on-disk metadata block errors out rather than decoding into nonsense.
161167
fn validate_tq_metadata(metadata: &TurboQuantMetadata) -> VortexResult<()> {
162168
vortex_ensure!(
163169
metadata.dimensions >= MIN_DIMENSION,
@@ -175,6 +181,8 @@ fn validate_tq_metadata(metadata: &TurboQuantMetadata) -> VortexResult<()> {
175181
TurboQuantConfig::try_new(metadata.bit_width, metadata.seed, metadata.num_rounds).map(|_| ())
176182
}
177183

184+
/// Validate that `dtype` matches the storage shape produced by [`tq_storage_dtype`] for
185+
/// `metadata`. Called from [`TurboQuant::validate_dtype`].
178186
fn validate_tq_storage_dtype(metadata: &TurboQuantMetadata, dtype: &DType) -> VortexResult<()> {
179187
let DType::Struct(fields, _) = dtype else {
180188
vortex_bail!("TurboQuant storage dtype must be a Struct, got {dtype}");

0 commit comments

Comments
 (0)