pub struct PqCodec {
pub dim: usize,
pub m: usize,
pub k: usize,
pub sub_dim: usize,
/* private fields */
}Expand description
PQ codec with trained codebooks.
Fields§
§dim: usizeOriginal vector dimensionality.
m: usizeNumber of subvectors (subspaces).
k: usizeCentroids per subvector (fixed at 256 for u8 encoding).
sub_dim: usizeDimensions per subvector: dim / m.
Implementations§
Source§impl PqCodec
impl PqCodec
Sourcepub fn with_governor(self, governor: Arc<MemoryGovernor>) -> Self
pub fn with_governor(self, governor: Arc<MemoryGovernor>) -> Self
Attach a memory governor to this codec.
Once set, heap-significant operations (train, encode_batch,
build_distance_table, decode, to_bytes) will charge the
EngineId::Vector budget before allocating and release the reservation
when the returned value is dropped (RAII). When no governor is set
those operations proceed unconditionally, preserving backward
compatibility with callers that do not use the memory governor.
The governor is a runtime concern only — it is not serialized.
Sourcepub fn train(
vectors: &[&[f32]],
dim: usize,
m: usize,
k: usize,
max_iter: usize,
) -> Self
pub fn train( vectors: &[&[f32]], dim: usize, m: usize, k: usize, max_iter: usize, ) -> Self
Train PQ codebooks from a set of training vectors via k-means.
m = number of subvectors (must divide dim evenly).
k = centroids per subvector (typically 256).
max_iter = k-means iterations (20 is usually sufficient).
Sourcepub fn encode(&self, vector: &[f32]) -> Vec<u8> ⓘ
pub fn encode(&self, vector: &[f32]) -> Vec<u8> ⓘ
Encode a vector: for each subvector, find the nearest centroid index.
This is a per-vector hot-path operation. Governor charging is
intentionally skipped here to avoid atomic overhead on every candidate
during search; use [encode_batch] for bulk encoding with budget
enforcement.
Sourcepub fn encode_batch(&self, vectors: &[&[f32]]) -> Result<Vec<u8>, VectorError>
pub fn encode_batch(&self, vectors: &[&[f32]]) -> Result<Vec<u8>, VectorError>
Batch encode all vectors into a contiguous byte array.
Charges m * vectors.len() bytes to the governor budget (if set)
before allocating the output buffer. The guard is released at
the end of this call — the buffer itself remains alive.
Sourcepub fn build_distance_table(
&self,
query: &[f32],
) -> Result<Vec<Vec<f32>>, VectorError>
pub fn build_distance_table( &self, query: &[f32], ) -> Result<Vec<Vec<f32>>, VectorError>
Build an asymmetric distance table for a query vector.
Returns table[sub][centroid] = distance from query’s sub-vector
to each centroid. Pre-computing this table makes distance evaluation
O(M) per candidate instead of O(D).
Charges m * k * size_of::<f32>() bytes to the governor (if set)
before allocating the table.
Sourcepub fn asymmetric_distance(&self, table: &[Vec<f32>], code: &[u8]) -> f32
pub fn asymmetric_distance(&self, table: &[Vec<f32>], code: &[u8]) -> f32
Compute asymmetric distance using a precomputed distance table.
O(M) per candidate — just M table lookups and additions.
Sourcepub fn decode(&self, code: &[u8]) -> Result<Vec<f32>, VectorError>
pub fn decode(&self, code: &[u8]) -> Result<Vec<f32>, VectorError>
Decode a PQ code back to an approximate FP32 vector.
Charges dim * size_of::<f32>() bytes to the governor (if set)
before allocating the output buffer.
Sourcepub fn to_bytes(&self) -> Result<Vec<u8>, VectorError>
pub fn to_bytes(&self) -> Result<Vec<u8>, VectorError>
Serialize the codec to bytes with a versioned magic header.
Format: [NDPQ\0\0 (6 bytes)][version: u8 = 1][msgpack payload]
Charges the estimated serialized size to the governor (if set) before
allocating the output buffer. The estimate is conservative:
m * k * sub_dim * size_of::<f32>() + 64 (header + framing overhead).
Sourcepub fn from_bytes(bytes: &[u8]) -> Result<Self, VectorError>
pub fn from_bytes(bytes: &[u8]) -> Result<Self, VectorError>
Deserialize the codec from bytes produced by Self::to_bytes.
Returns VectorError::InvalidMagic if the header does not match
NDPQ\0\0, and VectorError::UnsupportedVersion for unknown versions.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for PqCodec
impl<'de> Deserialize<'de> for PqCodec
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl<'__msgpack_de> FromMessagePack<'__msgpack_de> for PqCodec
impl<'__msgpack_de> FromMessagePack<'__msgpack_de> for PqCodec
Source§impl ToMessagePack for PqCodec
impl ToMessagePack for PqCodec
Source§impl VectorCodec for PqCodec
impl VectorCodec for PqCodec
Source§fn encode(&self, v: &[f32]) -> Self::Quantized
fn encode(&self, v: &[f32]) -> Self::Quantized
Encode an FP32 vector: one centroid index byte per subspace.
§Panics
UnifiedQuantizedVector::new fails only when the outlier bitmask does
not match the provided outlier slice. With outlier_bitmask = 0 and an
empty slice this can never happen. The expect is therefore unreachable
in practice.
Source§fn prepare_query(&self, q: &[f32]) -> Self::Query
fn prepare_query(&self, q: &[f32]) -> Self::Query
Prepare the query by precomputing the M×K asymmetric distance table.
The VectorCodec trait does not propagate errors. A PqCodec used
via this trait path is created by PqCodec::train which sets no
governor; build_distance_table therefore always returns Ok here.
If a governor is attached and its budget is exhausted the caller that
constructed the codec is responsible for handling the error — this impl
panics with a descriptive message so the budget violation is never
silently ignored.
Source§fn adc_lut(&self, q: &Self::Query) -> Option<AdcLut>
fn adc_lut(&self, q: &Self::Query) -> Option<AdcLut>
Build the AdcLut from the precomputed distance table for use by
SIMD rerank kernels (pshufb / vpermb).
Source§fn fast_symmetric_distance(
&self,
q: &Self::Quantized,
v: &Self::Quantized,
) -> f32
fn fast_symmetric_distance( &self, q: &Self::Quantized, v: &Self::Quantized, ) -> f32
Symmetric distance between two PQ-encoded vectors.
Both codes are decoded to approximate FP32 vectors via the codebook, then the squared L2 difference is accumulated. This is the correct definition of symmetric PQ distance: each vector is approximated by its nearest centroids, and the distance is computed in FP32.
Source§fn exact_asymmetric_distance(&self, q: &Self::Query, v: &Self::Quantized) -> f32
fn exact_asymmetric_distance(&self, q: &Self::Query, v: &Self::Quantized) -> f32
Asymmetric ADC distance: precomputed distance table vs stored code.
O(M) per candidate — delegates to PqCodec::asymmetric_distance.
Source§type Quantized = PqQuantized
type Quantized = PqQuantized
UnifiedQuantizedVector
reference via AsRef.Auto Trait Implementations§
impl Freeze for PqCodec
impl RefUnwindSafe for PqCodec
impl Send for PqCodec
impl Sync for PqCodec
impl Unpin for PqCodec
impl UnsafeUnpin for PqCodec
impl UnwindSafe for PqCodec
Blanket Implementations§
Source§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
Source§type ArchivedMetadata = ()
type ArchivedMetadata = ()
Source§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> LayoutRaw for T
impl<T> LayoutRaw for T
Source§fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
Source§impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
Source§unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
Source§fn resolve_niched(out: Place<NichedOption<T, N1>>)
fn resolve_niched(out: Place<NichedOption<T, N1>>)
out indicating that a T is niched.Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.