1use std::io;
4use std::mem::size_of;
5
6use serde::{Deserialize, Serialize};
7
8use crate::directories::{FileHandle, OwnedBytes};
9use crate::dsl::DenseVectorQuantization;
10use crate::segment::format::{DOC_ID_ENTRY_SIZE, FLAT_BINARY_HEADER_SIZE, FLAT_BINARY_MAGIC};
11use crate::structures::simd::{batch_f32_to_f16, batch_f32_to_u8, f16_to_f32, u8_to_f32};
12
13#[inline]
19pub fn dequantize_raw(
20 raw: &[u8],
21 quant: DenseVectorQuantization,
22 num_floats: usize,
23 out: &mut [f32],
24) {
25 debug_assert!(out.len() >= num_floats);
26 match quant {
27 DenseVectorQuantization::F32 => {
28 debug_assert!(
29 (raw.as_ptr() as usize).is_multiple_of(std::mem::align_of::<f32>()),
30 "f32 vector data not 4-byte aligned"
31 );
32 out[..num_floats].copy_from_slice(unsafe {
33 std::slice::from_raw_parts(raw.as_ptr() as *const f32, num_floats)
34 });
35 }
36 DenseVectorQuantization::F16 => {
37 debug_assert!(
38 (raw.as_ptr() as usize).is_multiple_of(std::mem::align_of::<u16>()),
39 "f16 vector data not 2-byte aligned"
40 );
41 let f16_slice =
42 unsafe { std::slice::from_raw_parts(raw.as_ptr() as *const u16, num_floats) };
43 for (i, &h) in f16_slice.iter().enumerate() {
44 out[i] = f16_to_f32(h);
45 }
46 }
47 DenseVectorQuantization::UInt8 => {
48 for (i, &b) in raw.iter().enumerate().take(num_floats) {
49 out[i] = u8_to_f32(b);
50 }
51 }
52 DenseVectorQuantization::Binary => {
53 unreachable!("Binary vectors use raw bytes, not f32 dequantization");
54 }
55 }
56}
57
58pub struct FlatVectorData;
71
72impl FlatVectorData {
73 pub fn write_binary_header(
75 dim: usize,
76 num_vectors: usize,
77 quant: DenseVectorQuantization,
78 writer: &mut dyn std::io::Write,
79 ) -> std::io::Result<()> {
80 writer.write_all(&FLAT_BINARY_MAGIC.to_le_bytes())?;
81 writer.write_all(&(dim as u32).to_le_bytes())?;
82 writer.write_all(&(num_vectors as u32).to_le_bytes())?;
83 writer.write_all(&[quant.tag(), 0, 0, 0])?; Ok(())
85 }
86
87 pub fn serialized_binary_size(
89 dim: usize,
90 num_vectors: usize,
91 quant: DenseVectorQuantization,
92 ) -> usize {
93 let bytes_per_vector = match quant {
94 DenseVectorQuantization::Binary => dim.div_ceil(8),
95 _ => dim * quant.element_size(),
96 };
97 FLAT_BINARY_HEADER_SIZE + num_vectors * bytes_per_vector + num_vectors * DOC_ID_ENTRY_SIZE
98 }
99
100 pub fn serialize_binary_from_flat_streaming(
105 dim: usize,
106 flat_vectors: &[f32],
107 doc_ids: &[(u32, u16)],
108 quant: DenseVectorQuantization,
109 writer: &mut dyn std::io::Write,
110 ) -> std::io::Result<()> {
111 let num_vectors = doc_ids.len();
112 Self::write_binary_header(dim, num_vectors, quant, writer)?;
113
114 match quant {
115 DenseVectorQuantization::F32 => {
116 let bytes: &[u8] = unsafe {
117 std::slice::from_raw_parts(
118 flat_vectors.as_ptr() as *const u8,
119 std::mem::size_of_val(flat_vectors),
120 )
121 };
122 writer.write_all(bytes)?;
123 }
124 DenseVectorQuantization::F16 => {
125 let mut buf = vec![0u16; dim];
126 for v in flat_vectors.chunks_exact(dim) {
127 batch_f32_to_f16(v, &mut buf);
128 let bytes: &[u8] =
129 unsafe { std::slice::from_raw_parts(buf.as_ptr() as *const u8, dim * 2) };
130 writer.write_all(bytes)?;
131 }
132 }
133 DenseVectorQuantization::UInt8 => {
134 let mut buf = vec![0u8; dim];
135 for v in flat_vectors.chunks_exact(dim) {
136 batch_f32_to_u8(v, &mut buf);
137 writer.write_all(&buf)?;
138 }
139 }
140 DenseVectorQuantization::Binary => {
141 unreachable!("Binary quantization should use serialize_binary_from_bits_streaming");
143 }
144 }
145
146 for &(doc_id, ordinal) in doc_ids {
147 writer.write_all(&doc_id.to_le_bytes())?;
148 writer.write_all(&ordinal.to_le_bytes())?;
149 }
150
151 Ok(())
152 }
153
154 pub fn serialize_binary_from_bits_streaming(
159 dim_bits: usize,
160 packed_vectors: &[u8],
161 doc_ids: &[(u32, u16)],
162 writer: &mut dyn std::io::Write,
163 ) -> std::io::Result<()> {
164 let num_vectors = doc_ids.len();
165 let byte_len = dim_bits.div_ceil(8);
166 debug_assert_eq!(packed_vectors.len(), num_vectors * byte_len);
167
168 Self::write_binary_header(
169 dim_bits,
170 num_vectors,
171 DenseVectorQuantization::Binary,
172 writer,
173 )?;
174 writer.write_all(packed_vectors)?;
175
176 for &(doc_id, ordinal) in doc_ids {
177 writer.write_all(&doc_id.to_le_bytes())?;
178 writer.write_all(&ordinal.to_le_bytes())?;
179 }
180
181 Ok(())
182 }
183
184 pub fn write_raw_vector_bytes(
188 raw_bytes: &[u8],
189 writer: &mut dyn std::io::Write,
190 ) -> std::io::Result<()> {
191 writer.write_all(raw_bytes)
192 }
193}
194
195#[derive(Debug, Clone)]
207pub struct LazyFlatVectorData {
208 pub dim: usize,
210 pub num_vectors: usize,
212 pub quantization: DenseVectorQuantization,
214 doc_ids_bytes: OwnedBytes,
216 handle: FileHandle,
218 vectors_offset: u64,
220 vbs: usize,
222}
223
224impl LazyFlatVectorData {
225 pub async fn open(handle: FileHandle) -> io::Result<Self> {
230 let header = handle
232 .read_bytes_range(0..FLAT_BINARY_HEADER_SIZE as u64)
233 .await?;
234 let hdr = header.as_slice();
235
236 let magic = u32::from_le_bytes([hdr[0], hdr[1], hdr[2], hdr[3]]);
237 if magic != FLAT_BINARY_MAGIC {
238 return Err(io::Error::new(
239 io::ErrorKind::InvalidData,
240 "Invalid FlatVectorData binary magic",
241 ));
242 }
243
244 let dim = u32::from_le_bytes([hdr[4], hdr[5], hdr[6], hdr[7]]) as usize;
245 let num_vectors = u32::from_le_bytes([hdr[8], hdr[9], hdr[10], hdr[11]]) as usize;
246 let quantization = DenseVectorQuantization::from_tag(hdr[12]).ok_or_else(|| {
247 io::Error::new(
248 io::ErrorKind::InvalidData,
249 format!("Unknown quantization tag: {}", hdr[12]),
250 )
251 })?;
252 let vbs = if quantization == DenseVectorQuantization::Binary {
254 dim.div_ceil(8)
255 } else {
256 dim * quantization.element_size()
257 };
258 let vectors_byte_len = num_vectors * vbs;
259 let doc_ids_start = (FLAT_BINARY_HEADER_SIZE + vectors_byte_len) as u64;
260 let doc_ids_byte_len = (num_vectors * DOC_ID_ENTRY_SIZE) as u64;
261
262 let doc_ids_bytes = handle
263 .read_bytes_range(doc_ids_start..doc_ids_start + doc_ids_byte_len)
264 .await?;
265
266 Ok(Self {
267 dim,
268 num_vectors,
269 quantization,
270 doc_ids_bytes,
271 handle,
272 vectors_offset: FLAT_BINARY_HEADER_SIZE as u64,
273 vbs,
274 })
275 }
276
277 #[cfg(feature = "native")]
284 pub fn advise_random_access(&self) {
285 let data_len = (self.num_vectors * self.vbs) as u64;
286 self.handle.madvise_range(
287 self.vectors_offset..self.vectors_offset + data_len,
288 libc::MADV_RANDOM,
289 );
290 }
291
292 #[cfg(feature = "native")]
299 pub fn prefetch_vectors(&self, sorted_flat_indexes: impl IntoIterator<Item = usize>) {
300 const COALESCE_GAP: u64 = 64 * 1024;
302 let vbs = self.vbs as u64;
303 let mut iter = sorted_flat_indexes.into_iter();
304 let Some(first) = iter.next() else {
305 return;
306 };
307 let mut run_start = self.vectors_offset + first as u64 * vbs;
308 let mut run_end = run_start + vbs;
309 for idx in iter {
310 let start = self.vectors_offset + idx as u64 * vbs;
311 if start <= run_end + COALESCE_GAP {
312 run_end = start + vbs;
313 } else {
314 self.handle
315 .madvise_range(run_start..run_end, libc::MADV_WILLNEED);
316 run_start = start;
317 run_end = start + vbs;
318 }
319 }
320 self.handle
321 .madvise_range(run_start..run_end, libc::MADV_WILLNEED);
322 }
323
324 pub async fn read_vector_into(&self, idx: usize, out: &mut [f32]) -> io::Result<()> {
329 debug_assert!(out.len() >= self.dim);
330 let vbs = self.vector_byte_size();
331 let byte_offset = self.vectors_offset + (idx * vbs) as u64;
332 let bytes = self
333 .handle
334 .read_bytes_range(byte_offset..byte_offset + vbs as u64)
335 .await?;
336 let raw = bytes.as_slice();
337
338 dequantize_raw(raw, self.quantization, self.dim, out);
339 Ok(())
340 }
341
342 pub async fn get_vector(&self, idx: usize) -> io::Result<Vec<f32>> {
344 let mut vector = vec![0f32; self.dim];
345 self.read_vector_into(idx, &mut vector).await?;
346 Ok(vector)
347 }
348
349 pub async fn read_vector_raw_into(&self, idx: usize, out: &mut [u8]) -> io::Result<()> {
354 let vbs = self.vector_byte_size();
355 debug_assert!(out.len() >= vbs);
356 let byte_offset = self.vectors_offset + (idx * vbs) as u64;
357 let bytes = self
358 .handle
359 .read_bytes_range(byte_offset..byte_offset + vbs as u64)
360 .await?;
361 out[..vbs].copy_from_slice(bytes.as_slice());
362 Ok(())
363 }
364
365 pub async fn read_vectors_batch(
371 &self,
372 start_idx: usize,
373 count: usize,
374 ) -> io::Result<OwnedBytes> {
375 debug_assert!(start_idx + count <= self.num_vectors);
376 let vbs = self.vector_byte_size();
377 let byte_offset = self.vectors_offset + (start_idx * vbs) as u64;
378 let byte_len = (count * vbs) as u64;
379 self.handle
380 .read_bytes_range(byte_offset..byte_offset + byte_len)
381 .await
382 }
383
384 #[cfg(feature = "sync")]
386 pub fn read_vector_raw_into_sync(&self, idx: usize, out: &mut [u8]) -> io::Result<()> {
387 let vbs = self.vector_byte_size();
388 debug_assert!(out.len() >= vbs);
389 let byte_offset = self.vectors_offset + (idx * vbs) as u64;
390 let bytes = self
391 .handle
392 .read_bytes_range_sync(byte_offset..byte_offset + vbs as u64)?;
393 out[..vbs].copy_from_slice(bytes.as_slice());
394 Ok(())
395 }
396
397 #[cfg(feature = "sync")]
399 pub fn read_vectors_batch_sync(
400 &self,
401 start_idx: usize,
402 count: usize,
403 ) -> io::Result<OwnedBytes> {
404 debug_assert!(start_idx + count <= self.num_vectors);
405 let vbs = self.vector_byte_size();
406 let byte_offset = self.vectors_offset + (start_idx * vbs) as u64;
407 let byte_len = (count * vbs) as u64;
408 self.handle
409 .read_bytes_range_sync(byte_offset..byte_offset + byte_len)
410 }
411
412 pub fn flat_indexes_for_doc_range(&self, doc_id: u32) -> (usize, usize) {
418 let n = self.num_vectors;
419 let start = {
420 let mut lo = 0usize;
421 let mut hi = n;
422 while lo < hi {
423 let mid = lo + (hi - lo) / 2;
424 if self.doc_id_at(mid) < doc_id {
425 lo = mid + 1;
426 } else {
427 hi = mid;
428 }
429 }
430 lo
431 };
432 let mut count = 0;
433 let mut i = start;
434 while i < n && self.doc_id_at(i) == doc_id {
435 count += 1;
436 i += 1;
437 }
438 (start, count)
439 }
440
441 pub fn flat_indexes_for_doc(&self, doc_id: u32) -> (usize, Vec<(u32, u16)>) {
448 let n = self.num_vectors;
449 let start = {
451 let mut lo = 0usize;
452 let mut hi = n;
453 while lo < hi {
454 let mid = lo + (hi - lo) / 2;
455 if self.doc_id_at(mid) < doc_id {
456 lo = mid + 1;
457 } else {
458 hi = mid;
459 }
460 }
461 lo
462 };
463 let mut entries = Vec::new();
465 let mut i = start;
466 while i < n {
467 let (did, ord) = self.get_doc_id(i);
468 if did != doc_id {
469 break;
470 }
471 entries.push((did, ord));
472 i += 1;
473 }
474 (start, entries)
475 }
476
477 #[inline]
479 fn doc_id_at(&self, idx: usize) -> u32 {
480 let off = idx * DOC_ID_ENTRY_SIZE;
481 let d = &self.doc_ids_bytes[off..];
482 u32::from_le_bytes([d[0], d[1], d[2], d[3]])
483 }
484
485 #[inline]
487 pub fn get_doc_id(&self, idx: usize) -> (u32, u16) {
488 let off = idx * DOC_ID_ENTRY_SIZE;
489 let d = &self.doc_ids_bytes[off..];
490 let doc_id = u32::from_le_bytes([d[0], d[1], d[2], d[3]]);
491 let ordinal = u16::from_le_bytes([d[4], d[5]]);
492 (doc_id, ordinal)
493 }
494
495 #[inline]
497 pub fn vector_byte_size(&self) -> usize {
498 self.vbs
499 }
500
501 pub fn vector_bytes_len(&self) -> u64 {
503 (self.num_vectors as u64) * (self.vector_byte_size() as u64)
504 }
505
506 pub fn vectors_byte_offset(&self) -> u64 {
508 self.vectors_offset
509 }
510
511 pub fn handle(&self) -> &FileHandle {
513 &self.handle
514 }
515
516 pub fn estimated_memory_bytes(&self) -> usize {
518 size_of::<Self>() + size_of::<OwnedBytes>()
519 }
520}
521
522#[derive(Debug, Clone, Serialize, Deserialize)]
527pub struct IVFRaBitQIndexData {
528 pub index: crate::structures::IVFRaBitQIndex,
529 pub codebook: crate::structures::RaBitQCodebook,
530}
531
532impl IVFRaBitQIndexData {
533 pub fn to_bytes(&self) -> std::io::Result<Vec<u8>> {
534 bincode::serde::encode_to_vec(self, bincode::config::standard())
535 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
536 }
537
538 pub fn from_bytes(data: &[u8]) -> std::io::Result<Self> {
539 bincode::serde::decode_from_slice(data, bincode::config::standard())
540 .map(|(v, _)| v)
541 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
542 }
543}
544
545#[derive(Debug, Clone, Serialize, Deserialize)]
550pub struct ScaNNIndexData {
551 pub index: crate::structures::IVFPQIndex,
552 pub codebook: crate::structures::PQCodebook,
553}
554
555impl ScaNNIndexData {
556 pub fn to_bytes(&self) -> std::io::Result<Vec<u8>> {
557 bincode::serde::encode_to_vec(self, bincode::config::standard())
558 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
559 }
560
561 pub fn from_bytes(data: &[u8]) -> std::io::Result<Self> {
562 bincode::serde::decode_from_slice(data, bincode::config::standard())
563 .map(|(v, _)| v)
564 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
565 }
566}