From aa967eefd7aa3788aab4bd735c1ab9c5f32a0d94 Mon Sep 17 00:00:00 2001 From: gouyt13clear Date: Wed, 16 Sep 2026 00:42:22 +0800 Subject: [PATCH] Code-review - Make packed-data access and aligned ownership safe. - Preserve contiguous QG rows with a single vector. - Change IVF inner-product routing and pruning. - Validate index state, search arguments, allocations, and file input. - Preserve existing indexes when loading fails. - Correct SIMD feature detection and unaligned accesses. - Improve worker cleanup and local thread-count handling. --- README.md | 8 - docs/docs/assets/img/acc_bench.png | Bin 431749 -> 0 bytes docs/docs/index.md | 8 - include/rabitqlib/index/estimator.hpp | 43 ++- include/rabitqlib/index/ivf/initializer.hpp | 91 +++-- include/rabitqlib/index/ivf/ivf.hpp | 275 +++++++++---- include/rabitqlib/index/lut.hpp | 39 +- include/rabitqlib/index/query.hpp | 13 +- .../rabitqlib/index/symqg/detail/pipnn.hpp | 2 - include/rabitqlib/index/symqg/qg.hpp | 351 ++++++++++++----- include/rabitqlib/index/symqg/qg_builder.hpp | 44 ++- .../rabitqlib/quantization/data_layout.hpp | 338 +++++++++++----- include/rabitqlib/quantization/rabitq.hpp | 24 +- .../rabitqlib/quantization/rabitq_impl.hpp | 88 ++++- include/rabitqlib/simd/space_dispatch.hpp | 2 + include/rabitqlib/simd/warmup_dispatch.hpp | 18 + include/rabitqlib/utils/array.hpp | 20 +- include/rabitqlib/utils/buffer.hpp | 20 +- include/rabitqlib/utils/cpu_features.hpp | 10 + include/rabitqlib/utils/io.hpp | 125 ++++-- include/rabitqlib/utils/memory.hpp | 59 ++- include/rabitqlib/utils/rotator.hpp | 13 + include/rabitqlib/utils/space.hpp | 22 +- include/rabitqlib/utils/warmup_space.hpp | 9 + python_bindings/ivf_bindings.cpp | 12 +- python_bindings/symqg_bindings.cpp | 17 +- scripts/check-tidy.sh | 6 +- src/simd/dispatch.cpp | 50 ++- src/simd/fastscan_avx512.cpp | 4 +- src/simd/space_avx2.cpp | 8 +- src/simd/space_avx512.cpp | 8 +- src/simd/warmup_avx2.cpp | 50 +-- src/simd/warmup_avx512.cpp | 17 +- src/utils/cpu_features.cpp | 106 ++++- tests/python/test_ivf.py | 17 + tests/python/test_symqg.py | 13 + .../unit/rabitqlib/fastscan/fastscan_test.cpp | 110 ++++++ .../unit/rabitqlib/index/initializer_test.cpp | 45 +++ tests/unit/rabitqlib/index/ivf_test.cpp | 238 ++++++++++++ tests/unit/rabitqlib/index/qg_test.cpp | 363 +++++++++++++++++- .../quantization/data_layout_test.cpp | 184 +++++++++ tests/unit/rabitqlib/utils/buffer_test.cpp | 39 ++ .../rabitqlib/utils/cpu_features_test.cpp | 82 +++- tests/unit/rabitqlib/utils/io_test.cpp | 110 ++++++ tests/unit/rabitqlib/utils/mask_ip_test.cpp | 11 +- tests/unit/rabitqlib/utils/memory_test.cpp | 38 ++ tests/unit/rabitqlib/utils/rotator_test.cpp | 25 +- tests/unit/rabitqlib/utils/space_test.cpp | 56 ++- 48 files changed, 2720 insertions(+), 511 deletions(-) delete mode 100644 docs/docs/assets/img/acc_bench.png create mode 100644 tests/unit/rabitqlib/index/initializer_test.cpp create mode 100644 tests/unit/rabitqlib/quantization/data_layout_test.cpp create mode 100644 tests/unit/rabitqlib/utils/buffer_test.cpp create mode 100644 tests/unit/rabitqlib/utils/io_test.cpp create mode 100644 tests/unit/rabitqlib/utils/memory_test.cpp diff --git a/README.md b/README.md index 7f5626e..d53963f 100644 --- a/README.md +++ b/README.md @@ -135,14 +135,6 @@ RaBitQ is developed by the University, Singapore. A GPU implementation is also available in [cuvs_rabitq](https://github.com/Stardust-SJF/cuvs_rabitq/tree/cuvs_ivf_rabitq). -## Accuracy at a glance - -![RaBitQ estimation error benchmark across MSong, YouTube, OpenAI embeddings, Word2Vec, and GIST](docs/docs/assets/img/acc_bench.png) - -*Average and maximum relative estimation error across six datasets; lower is -better. Results from the -[SIGMOD camera-ready paper](https://doi.org/10.1145/3725413).* - ## RaBitQ across the vector-search ecosystem The projects below illustrate adoption of RaBitQ techniques across vector diff --git a/docs/docs/assets/img/acc_bench.png b/docs/docs/assets/img/acc_bench.png deleted file mode 100644 index 33180bbbf3f0072ac9617146c3dc18ecff5ebd44..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 431749 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 ~8t;tPza;u1SiN&{ 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 -## Accuracy at a glance - -![RaBitQ estimation error benchmark across MSong, YouTube, OpenAI embeddings, Word2Vec, and GIST](assets/img/acc_bench.png) - -*Average and maximum relative estimation error across six datasets; lower is -better. Results from the -[SIGMOD camera-ready paper](https://doi.org/10.1145/3725413).* - ## Start with Python Install the latest release from PyPI: diff --git a/include/rabitqlib/index/estimator.hpp b/include/rabitqlib/index/estimator.hpp index 3f75c05..b6b00ab 100644 --- a/include/rabitqlib/index/estimator.hpp +++ b/include/rabitqlib/index/estimator.hpp @@ -77,11 +77,19 @@ inline void split_batch_estdist( } } - ConstRowMajorArrayMap f_add_arr(cur_batch.f_add(), 1, fastscan::kBatchSize); + std::array f_add_values; + std::array f_rescale_values; + std::array f_error_values; + cur_batch.f_add().copy_to(f_add_values.data(), f_add_values.size()); + cur_batch.f_rescale().copy_to(f_rescale_values.data(), f_rescale_values.size()); + cur_batch.f_error().copy_to(f_error_values.data(), f_error_values.size()); + ConstRowMajorArrayMap f_add_arr(f_add_values.data(), 1, fastscan::kBatchSize); ConstRowMajorArrayMap f_rescale_arr( - cur_batch.f_rescale(), 1, fastscan::kBatchSize + f_rescale_values.data(), 1, fastscan::kBatchSize + ); + ConstRowMajorArrayMap f_error_arr( + f_error_values.data(), 1, fastscan::kBatchSize ); - ConstRowMajorArrayMap f_error_arr(cur_batch.f_error(), 1, fastscan::kBatchSize); RowMajorArrayMap est_dist_arr(est_distance, 1, fastscan::kBatchSize); RowMajorArrayMap ip_x0_qr_arr(ip_x0_qr, 1, fastscan::kBatchSize); @@ -145,7 +153,13 @@ inline void split_single_fulldist_direct( ConstExDataMap cur_ex(ex_data, padded_dim, ex_bits); // [TODO: optimize this function] - ip_x0_qr = Kernel::mask_ip_x0_q(q_obj.rotated_query(), cur_bin.bin_code(), padded_dim); + // Direct HNSW kernels retain their legacy word-typed ABI. Generic kernels use the + // byte-oriented overload and do not manufacture a typed view of packed storage. + ip_x0_qr = Kernel::mask_ip_x0_q( + q_obj.rotated_query(), + reinterpret_cast(cur_bin.bin_code()), + padded_dim + ); est_dist = cur_ex.f_add_ex() + g_add + @@ -176,9 +190,13 @@ inline void qg_batch_estdist( ); ConstRowMajorArrayMap ip_arr(accu_res.data(), 1, fastscan::kBatchSize); - ConstRowMajorArrayMap f_add_arr(cur_batch.f_add(), 1, fastscan::kBatchSize); + std::array f_add_values; + std::array f_rescale_values; + cur_batch.f_add().copy_to(f_add_values.data(), f_add_values.size()); + cur_batch.f_rescale().copy_to(f_rescale_values.data(), f_rescale_values.size()); + ConstRowMajorArrayMap f_add_arr(f_add_values.data(), 1, fastscan::kBatchSize); ConstRowMajorArrayMap f_rescale_arr( - cur_batch.f_rescale(), 1, fastscan::kBatchSize + f_rescale_values.data(), 1, fastscan::kBatchSize ); RowMajorArrayMap est_dist_arr(est_distance, 1, fastscan::kBatchSize); @@ -210,8 +228,14 @@ inline void qg_batch_estdist( } ConstRowMajorArrayMap ip_arr(accu_values.data(), 1, fastscan::kBatchSize); - ConstRowMajorArrayMap f_add_arr(cur_batch.f_add(), 1, fastscan::kBatchSize); - ConstRowMajorArrayMap f_rescale_arr(cur_batch.f_rescale(), 1, fastscan::kBatchSize); + std::array f_add_values; + std::array f_rescale_values; + cur_batch.f_add().copy_to(f_add_values.data(), f_add_values.size()); + cur_batch.f_rescale().copy_to(f_rescale_values.data(), f_rescale_values.size()); + ConstRowMajorArrayMap f_add_arr(f_add_values.data(), 1, fastscan::kBatchSize); + ConstRowMajorArrayMap f_rescale_arr( + f_rescale_values.data(), 1, fastscan::kBatchSize + ); RowMajorArrayMap est_dist_arr(est_distance, 1, fastscan::kBatchSize); @@ -294,8 +318,9 @@ inline void split_single_estdist_direct( ) { ConstBinDataMap cur_bin(bin_data, padded_dim); + // Direct HNSW kernels retain their legacy word-typed ABI; see the note above. ip_x0_qr = Kernel::warmup_ip_x0_q_512( - cur_bin.bin_code(), + reinterpret_cast(cur_bin.bin_code()), q_obj.query_bin(), q_obj.delta(), q_obj.vl(), diff --git a/include/rabitqlib/index/ivf/initializer.hpp b/include/rabitqlib/index/ivf/initializer.hpp index 8890692..d5458b3 100644 --- a/include/rabitqlib/index/ivf/initializer.hpp +++ b/include/rabitqlib/index/ivf/initializer.hpp @@ -21,9 +21,13 @@ namespace rabitqlib::ivf { template inline void parallel_for(size_t start, size_t end, size_t numThreads, Function fn) { - if (numThreads <= 0) { - numThreads = std::thread::hardware_concurrency(); + if (start >= end) { + return; } + if (numThreads == 0) { + numThreads = std::max(1, std::thread::hardware_concurrency()); + } + numThreads = std::min(numThreads, end - start); if (numThreads == 1) { for (size_t id = start; id < end; id++) { @@ -38,36 +42,49 @@ inline void parallel_for(size_t start, size_t end, size_t numThreads, Function f std::exception_ptr last_exception = nullptr; std::mutex last_except_mutex; - threads.reserve(numThreads); - for (size_t thread_id = 0; thread_id < numThreads; ++thread_id) { - threads.push_back(std::thread([&, thread_id] { - while (true) { - size_t id = current.fetch_add(1); - - if (id >= end) { - break; - } - - try { - fn(id, thread_id); - } catch (...) { - std::unique_lock last_except_lock(last_except_mutex); - last_exception = std::current_exception(); - /* - * This will work even when current is the largest value that - * size_t can fit, because fetch_add returns the previous value - * before the increment (what will result in overflow - * and produce 0 instead of current + 1). - */ - current = end; - break; - } + const auto join_threads = [&threads] { + for (auto& thread : threads) { + if (thread.joinable()) { + thread.join(); } - })); - } - for (auto& thread : threads) { - thread.join(); + } + }; + + try { + threads.reserve(numThreads); + for (size_t thread_id = 0; thread_id < numThreads; ++thread_id) { + threads.emplace_back([&, thread_id] { + while (true) { + size_t id = current.fetch_add(1); + + if (id >= end) { + break; + } + + try { + fn(id, thread_id); + } catch (...) { + std::unique_lock last_except_lock(last_except_mutex + ); + last_exception = std::current_exception(); + /* + * This will work even when current is the largest value that + * size_t can fit, because fetch_add returns the previous value + * before the increment (what will result in overflow + * and produce 0 instead of current + 1). + */ + current = end; + break; + } + } + }); + } + } catch (...) { + current = end; + join_threads(); + throw; } + join_threads(); if (last_exception) { std::rethrow_exception(last_exception); } @@ -97,10 +114,15 @@ inline Initializer::~Initializer() {} class FlatInitializer : public Initializer { private: std::vector centroids_; + MetricType metric_type_; public: - explicit FlatInitializer(size_t d, size_t k) - : Initializer(d, k), centroids_(num_cluster_ * dim_) {} + explicit FlatInitializer( + size_t d, size_t k, MetricType metric_type = MetricType::METRIC_L2 + ) + : Initializer(d, k), centroids_(num_cluster_ * dim_), metric_type_(metric_type) { + validate_metric_type(metric_type_); + } ~FlatInitializer() override = default; @@ -118,7 +140,10 @@ class FlatInitializer : public Initializer { std::vector> centroid_dist(this->num_cluster_); for (PID i = 0; i < num_cluster_; ++i) { centroid_dist[i].id = i; - centroid_dist[i].distance = std::sqrt(euclidean_sqr(query, centroid(i), dim_)); + centroid_dist[i].distance = + metric_type_ == METRIC_IP + ? dot_product_dis(query, centroid(i), dim_) + : std::sqrt(euclidean_sqr(query, centroid(i), dim_)); } std::partial_sort( centroid_dist.begin(), diff --git a/include/rabitqlib/index/ivf/ivf.hpp b/include/rabitqlib/index/ivf/ivf.hpp index 1cf6d70..80e814a 100644 --- a/include/rabitqlib/index/ivf/ivf.hpp +++ b/include/rabitqlib/index/ivf/ivf.hpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include @@ -32,16 +31,23 @@ namespace rabitqlib::ivf { class IVF { private: - std::unique_ptr initer_; // initializer for candidate clusters - char* batch_data_ = nullptr; // 1-bit code and factors - char* ex_data_ = nullptr; // extra-bit codes or original float32 vectors - PID* ids_ = nullptr; // PID of vectors (organized by clusters) - size_t num_ = 0; // num of data points - size_t dim_ = 0; // dimension of data points - size_t padded_dim_ = 0; // dimension after padding - size_t num_cluster_ = 0; // num of centroids (clusters) - bool raw_reranking_ = false; // raw vectors replace extra-bit codes - size_t ex_bits_ = 0; // total bits = ex_bits_ + 1 + using ByteStorage = + std::vector>; + using FloatStorage = std::vector>; + using IdStorage = std::vector>; + + std::unique_ptr initer_; // initializer for candidate clusters + ByteStorage batch_storage_; // 1-bit code and factors + ByteStorage ex_storage_; // extra-bit codes and packed factors + FloatStorage raw_storage_; // original vectors for raw reranking + IdStorage id_storage_; // point IDs organized by cluster + size_t num_ = 0; // num of data points + size_t dim_ = 0; // dimension of data points + size_t padded_dim_ = 0; // dimension after padding + size_t num_cluster_ = 0; // num of centroids (clusters) + bool raw_reranking_ = false; // raw vectors replace extra-bit codes + bool ready_ = false; // construction or loading completed + size_t ex_bits_ = 0; // total bits = ex_bits_ + 1 RotatorType type_ = RotatorType::FhtKacRotator; // type of rotator std::unique_ptr> rotator_; // Data Rotator std::vector cluster_lst_; // List of clusters in ivf @@ -73,15 +79,59 @@ class IVF { [[nodiscard]] size_t ex_data_bytes() const { return rerank_vector_bytes() * num_; } + [[nodiscard]] char* batch_data() { + return reinterpret_cast(batch_storage_.data()); + } + + [[nodiscard]] const char* batch_data() const { + return reinterpret_cast(batch_storage_.data()); + } + + [[nodiscard]] char* ex_data() { + return raw_reranking_ ? reinterpret_cast(raw_storage_.data()) + : reinterpret_cast(ex_storage_.data()); + } + + [[nodiscard]] const char* ex_data() const { + return raw_reranking_ ? reinterpret_cast(raw_storage_.data()) + : reinterpret_cast(ex_storage_.data()); + } + + [[nodiscard]] PID* ids() { return id_storage_.data(); } + + [[nodiscard]] const PID* ids() const { return id_storage_.data(); } + void allocate_memory(const std::vector&); void init_clusters(const std::vector&); void free_memory() { initer_.reset(); - std::free(std::exchange(batch_data_, nullptr)); - std::free(std::exchange(ex_data_, nullptr)); - std::free(std::exchange(ids_, nullptr)); + ByteStorage().swap(batch_storage_); + ByteStorage().swap(ex_storage_); + FloatStorage().swap(raw_storage_); + IdStorage().swap(id_storage_); + } + + void swap(IVF& other) noexcept { + using std::swap; + swap(initer_, other.initer_); + swap(batch_storage_, other.batch_storage_); + swap(ex_storage_, other.ex_storage_); + swap(raw_storage_, other.raw_storage_); + swap(id_storage_, other.id_storage_); + swap(num_, other.num_); + swap(dim_, other.dim_); + swap(padded_dim_, other.padded_dim_); + swap(num_cluster_, other.num_cluster_); + swap(raw_reranking_, other.raw_reranking_); + swap(ready_, other.ready_); + swap(ex_bits_, other.ex_bits_); + swap(type_, other.type_); + swap(rotator_, other.rotator_); + swap(cluster_lst_, other.cluster_lst_); + swap(metric_type_, other.metric_type_); + swap(ip_func_, other.ip_func_); } void @@ -149,13 +199,27 @@ inline IVF::IVF( if ((bits < 1 || bits > 9) && bits != 32) { throw std::invalid_argument("IVF bits must be in [1, 9] or 32 for raw reranking"); }; - if (raw_reranking_ && (n == 0 || n > buffer::kSearchBufferMaxPointCount || dim == 0 || - dim > std::numeric_limits::max() / sizeof(float) / n || - dim > (std::numeric_limits::max() / 32) - 64)) { - throw std::invalid_argument("Invalid raw IVF vector count or dimension"); + if (n == 0 || n > buffer::kSearchBufferMaxPointCount) { + throw std::invalid_argument("IVF point count exceeds the supported ID range"); } - rotator_.reset(choose_rotator(dim, type, round_up_to_multiple(dim_, 64))); - padded_dim_ = rotator_->size(); + if (cluster_num == 0 || cluster_num > buffer::kSearchBufferMaxPointCount) { + throw std::invalid_argument("IVF cluster count exceeds the supported ID range"); + } + if (dim == 0 || dim > (std::numeric_limits::max() / 32) - 64) { + throw std::invalid_argument("IVF dimension is invalid or too large"); + } + padded_dim_ = round_up_to_multiple(dim_, 64); + const size_t max_size = std::numeric_limits::max(); + const size_t batch_bytes = BatchDataMap::data_bytes(padded_dim_); + const size_t rerank_bytes = rerank_vector_bytes(); + if (n > max_size / sizeof(PID) || n > max_size / sizeof(float) / padded_dim_ || + n > max_size / batch_bytes || (rerank_bytes != 0 && n > max_size / rerank_bytes) || + cluster_num > max_size / sizeof(float) / padded_dim_ || + (type == RotatorType::MatrixRotator && dim > max_size / sizeof(float) / padded_dim_ + )) { + throw std::invalid_argument("IVF configuration exceeds addressable storage"); + } + rotator_.reset(choose_rotator(dim, type, padded_dim_)); /* check size */ assert(padded_dim_ % 64 == 0); assert(padded_dim_ >= dim_); @@ -177,6 +241,13 @@ inline void IVF::construct( bool faster = false, size_t num_threads = std::numeric_limits::max() ) { + if (num_ == 0 || dim_ == 0 || num_cluster_ == 0 || rotator_ == nullptr) { + throw std::logic_error("IVF must be configured before construction"); + } + if (data == nullptr || centroids == nullptr || cluster_ids == nullptr) { + throw std::invalid_argument("IVF construction inputs must not be null"); + } + // get id list for each cluster std::vector counts(num_cluster_, 0); std::vector> id_lists(num_cluster_); @@ -213,23 +284,29 @@ inline void IVF::construct( } this->initer_->add_vectors(rotated_centroids.data(), num_threads); + ready_ = true; } inline void IVF::allocate_memory(const std::vector& cluster_sizes) { + ready_ = false; free_memory(); cluster_lst_.clear(); if (num_cluster_ < 20000UL) { - this->initer_ = std::make_unique(padded_dim_, num_cluster_); + this->initer_ = + std::make_unique(padded_dim_, num_cluster_, metric_type_); } else { this->initer_ = std::make_unique(padded_dim_, num_cluster_); } - this->batch_data_ = - memory::align_allocate<64, char, true>(batch_data_bytes(cluster_sizes)); + batch_storage_ = ByteStorage(batch_data_bytes(cluster_sizes)); if (rerank_vector_bytes() > 0) { - this->ex_data_ = memory::align_allocate<64, char, true>(ex_data_bytes()); + if (raw_reranking_) { + raw_storage_ = FloatStorage(num_ * dim_); + } else { + ex_storage_ = ByteStorage(ex_data_bytes()); + } } - this->ids_ = memory::align_allocate<64, PID, true>(ids_bytes()); + id_storage_ = IdStorage(num_); this->ip_func_ = select_excode_ipfunc(ex_bits_); } @@ -247,13 +324,13 @@ inline void IVF::init_clusters(const std::vector& cluster_sizes) { size_t num_batches = div_round_up(num, fastscan::kBatchSize); char* current_batch_data = - batch_data_ + (BatchDataMap::data_bytes(padded_dim_) * added_batches); + batch_data() + (BatchDataMap::data_bytes(padded_dim_) * added_batches); char* current_ex_data = rerank_vector_bytes() > 0 - ? ex_data_ + (added_vectors * rerank_vector_bytes()) + ? ex_data() + (added_vectors * rerank_vector_bytes()) : nullptr; - PID* ids = ids_ + added_vectors; + PID* cluster_ids = ids() + added_vectors; - Cluster cur_cluster(num, current_batch_data, current_ex_data, ids); + Cluster cur_cluster(num, current_batch_data, current_ex_data, cluster_ids); this->cluster_lst_.push_back(std::move(cur_cluster)); added_vectors += num; @@ -317,9 +394,14 @@ inline void IVF::quantize_cluster( } inline void IVF::save(const char* filename) const { - if (cluster_lst_.size() == 0) { + if (!ready_ || initer_ == nullptr || rotator_ == nullptr || + cluster_lst_.size() != num_cluster_ || batch_storage_.empty() || + id_storage_.size() != num_) { throw std::logic_error("Cannot save an unconstructed IVF index"); } + if (filename == nullptr || filename[0] == '\0') { + throw std::invalid_argument("IVF save filename must not be empty"); + } std::ofstream output(filename, std::ios::binary); output.exceptions(std::ios::failbit | std::ios::badbit); @@ -356,32 +438,33 @@ inline void IVF::save(const char* filename) const { /* Save data */ this->initer_->save(output, filename); - output.write( - reinterpret_cast(batch_data_), - static_cast(batch_data_bytes(cluster_sizes)) - ); - output.write( - reinterpret_cast(ex_data_), static_cast(ex_data_bytes()) - ); - output.write(reinterpret_cast(ids_), static_cast(ids_bytes())); + output.write(batch_data(), static_cast(batch_data_bytes(cluster_sizes))); + if (ex_data_bytes() != 0) { + output.write(ex_data(), static_cast(ex_data_bytes())); + } + output.write(reinterpret_cast(ids()), static_cast(ids_bytes())); output.close(); } inline void IVF::load(const char* filename) { + if (filename == nullptr || filename[0] == '\0') { + throw std::invalid_argument("IVF load filename must not be empty"); + } std::ifstream input(filename, std::ios::binary); if (!input.is_open()) { throw std::runtime_error("Cannot open IVF index file"); } + IVF loaded; input.exceptions(std::ios::failbit | std::ios::badbit); input.seekg(0, std::ios::end); const auto file_bytes = static_cast(input.tellg()); input.seekg(0); uint64_t magic = 0; input.read(reinterpret_cast(&magic), sizeof(magic)); - raw_reranking_ = magic == kRawFormatMagic; - if (raw_reranking_) { + loaded.raw_reranking_ = magic == kRawFormatMagic; + if (loaded.raw_reranking_) { uint32_t version = 0; input.read(reinterpret_cast(&version), sizeof(version)); if (version != kRawFormatVersion) { @@ -392,21 +475,21 @@ inline void IVF::load(const char* filename) { } /* Load meta data */ - input.read(reinterpret_cast(&this->num_), sizeof(size_t)); - input.read(reinterpret_cast(&this->dim_), sizeof(size_t)); - input.read(reinterpret_cast(&this->num_cluster_), sizeof(size_t)); - input.read(reinterpret_cast(&this->ex_bits_), sizeof(size_t)); - input.read(reinterpret_cast(&type_), sizeof(type_)); - input.read(reinterpret_cast(&metric_type_), sizeof(metric_type_)); - validate_metric_type(metric_type_); - if ((raw_reranking_ && num_ == 0) || num_ > buffer::kSearchBufferMaxPointCount || - dim_ == 0 || num_cluster_ == 0 || - num_cluster_ > buffer::kSearchBufferMaxPointCount || ex_bits_ > 8 || - (raw_reranking_ && ex_bits_ != 0) || - dim_ > (std::numeric_limits::max() / 32) - 64) { + input.read(reinterpret_cast(&loaded.num_), sizeof(size_t)); + input.read(reinterpret_cast(&loaded.dim_), sizeof(size_t)); + input.read(reinterpret_cast(&loaded.num_cluster_), sizeof(size_t)); + input.read(reinterpret_cast(&loaded.ex_bits_), sizeof(size_t)); + input.read(reinterpret_cast(&loaded.type_), sizeof(loaded.type_)); + input.read(reinterpret_cast(&loaded.metric_type_), sizeof(loaded.metric_type_)); + validate_metric_type(loaded.metric_type_); + if (loaded.num_ == 0 || loaded.num_ > buffer::kSearchBufferMaxPointCount || + loaded.dim_ == 0 || loaded.num_cluster_ == 0 || + loaded.num_cluster_ > buffer::kSearchBufferMaxPointCount || loaded.ex_bits_ > 8 || + (loaded.raw_reranking_ && loaded.ex_bits_ != 0) || + loaded.dim_ > (std::numeric_limits::max() / 32) - 64) { throw std::runtime_error("Invalid IVF index metadata"); } - padded_dim_ = round_up_to_multiple(dim_, 64); + loaded.padded_dim_ = round_up_to_multiple(loaded.dim_, 64); // Bound every payload by the actual file before allocating or multiplying sizes. size_t remaining = file_bytes - static_cast(input.tellg()); const auto consume = [&remaining](size_t count, size_t bytes) { @@ -415,57 +498,73 @@ inline void IVF::load(const char* filename) { } remaining -= count * bytes; }; - consume(num_cluster_, sizeof(size_t)); - consume(num_, sizeof(PID)); - consume(num_, rerank_vector_bytes()); - if (type_ == RotatorType::MatrixRotator) { - consume(dim_, sizeof(float) * padded_dim_); - } else if (type_ == RotatorType::FhtKacRotator) { - consume(1, padded_dim_ / 2); + consume(loaded.num_cluster_, sizeof(size_t)); + consume(loaded.num_, sizeof(PID)); + consume(loaded.num_, loaded.rerank_vector_bytes()); + if (loaded.type_ == RotatorType::MatrixRotator) { + consume(loaded.dim_, sizeof(float) * loaded.padded_dim_); + } else if (loaded.type_ == RotatorType::FhtKacRotator) { + consume(1, loaded.padded_dim_ / 2); } else { throw std::runtime_error("Invalid IVF rotator type"); } - if (num_cluster_ < 20000UL) { - consume(num_cluster_, sizeof(float) * padded_dim_); + if (loaded.num_cluster_ < 20000UL) { + consume(loaded.num_cluster_, sizeof(float) * loaded.padded_dim_); } /* Load number of vectors of each cluster */ - std::vector cluster_sizes(num_cluster_, 0); + std::vector cluster_sizes(loaded.num_cluster_, 0); input.read( reinterpret_cast(cluster_sizes.data()), - static_cast(sizeof(size_t) * num_cluster_) + static_cast(sizeof(size_t) * loaded.num_cluster_) ); size_t total = 0; for (size_t size : cluster_sizes) { - if (size > num_ - total) { + if (size > loaded.num_ - total) { throw std::runtime_error("Invalid cluster counts in IVF index file"); } total += size; consume( div_round_up(size, fastscan::kBatchSize), - BatchDataMap::data_bytes(padded_dim_) + BatchDataMap::data_bytes(loaded.padded_dim_) ); } - if (total != num_) { + if (total != loaded.num_) { throw std::runtime_error("Invalid cluster counts in IVF index file"); } - rotator_.reset(choose_rotator(dim_, type_, padded_dim_)); + loaded.rotator_.reset( + choose_rotator(loaded.dim_, loaded.type_, loaded.padded_dim_) + ); /* Load rotator */ - this->rotator_->load(input); + loaded.rotator_->load(input); /* Load data */ - allocate_memory(cluster_sizes); - this->initer_->load(input, filename); - input.read(batch_data_, static_cast(batch_data_bytes(cluster_sizes))); - input.read(ex_data_, static_cast(ex_data_bytes())); - input.read(reinterpret_cast(ids_), static_cast(ids_bytes())); + loaded.allocate_memory(cluster_sizes); + loaded.initer_->load(input, filename); + input.read( + loaded.batch_data(), static_cast(loaded.batch_data_bytes(cluster_sizes)) + ); + if (loaded.ex_data_bytes() != 0) { + input.read(loaded.ex_data(), static_cast(loaded.ex_data_bytes())); + } + input.read( + reinterpret_cast(loaded.ids()), static_cast(loaded.ids_bytes()) + ); + for (size_t i = 0; i < loaded.num_; ++i) { + if (loaded.ids()[i] >= loaded.num_ || + loaded.ids()[i] >= buffer::kSearchBufferCheckedMask) { + throw std::runtime_error("Invalid point ID in IVF index file"); + } + } /* Init each cluster */ - init_clusters(cluster_sizes); + loaded.init_clusters(cluster_sizes); + loaded.ready_ = true; input.close(); + swap(loaded); } inline void IVF::search( @@ -492,6 +591,24 @@ inline void IVF::search( float* __restrict__ dists, bool use_hacc ) const { + if (!ready_ || initer_ == nullptr || rotator_ == nullptr || + cluster_lst_.size() != num_cluster_ || batch_storage_.empty() || + id_storage_.size() != num_) { + throw std::logic_error("IVF index must be constructed or loaded before search"); + } + if (query == nullptr) { + throw std::invalid_argument("IVF search query must not be null"); + } + if (results == nullptr) { + throw std::invalid_argument("IVF search results must not be null"); + } + if (k == 0 || k > num_ || k > buffer::kSearchBufferMaxPointCount) { + throw std::invalid_argument("IVF search k must be between 1 and the point count"); + } + if (nprobe == 0) { + throw std::invalid_argument("IVF search nprobe must be positive"); + } + nprobe = std::min(nprobe, num_cluster_); // corner case std::vector rotated_query(padded_dim_); this->rotator_->rotate(query, rotated_query.data()); @@ -514,10 +631,13 @@ inline void IVF::search( if (metric_type_ == METRIC_L2) { q_obj.set_g_add(dist); } else if (metric_type_ == METRIC_IP) { + const float residual_norm = std::sqrt( + euclidean_sqr(rotated_query.data(), initer_->centroid(cid), padded_dim_) + ); auto g_add_ip = dot_product( rotated_query.data(), initer_->centroid(cid), padded_dim_ ); - q_obj.set_g_add(dist, g_add_ip); + q_obj.set_g_add(residual_norm, g_add_ip); } else { // unsupported throw std::invalid_argument("Quantization only supports L2 and IP metrics"); @@ -526,11 +646,14 @@ inline void IVF::search( search_cluster(cur_cluster, q_obj, knns, use_hacc, query); } + const size_t found = knns.size(); if (dists != nullptr) { knns.copy_results(results, dists); + std::fill(dists + found, dists + k, std::numeric_limits::infinity()); } else { knns.copy_results(results); } + std::fill(results + found, results + k, kPidMax); } inline void IVF::search_cluster( diff --git a/include/rabitqlib/index/lut.hpp b/include/rabitqlib/index/lut.hpp index 7b135c6..242d941 100644 --- a/include/rabitqlib/index/lut.hpp +++ b/include/rabitqlib/index/lut.hpp @@ -2,8 +2,9 @@ #include #include +#include +#include #include -#include #include #include "rabitqlib/fastscan/fastscan.hpp" @@ -19,16 +20,37 @@ class Lut { static_assert(std::is_floating_point_v, "T must be a floating-point type in Lut"); private: + [[nodiscard]] static size_t checked_table_length(size_t padded_dim) { + if (padded_dim == 0 || padded_dim % 16 != 0) { + throw std::invalid_argument( + "FastScan dimension must be a positive multiple of 16" + ); + } + if (padded_dim > std::numeric_limits::max() / 4) { + throw std::length_error("FastScan lookup table is too large"); + } + return padded_dim * 4; + } + + [[nodiscard]] static size_t checked_storage_length(size_t padded_dim, bool use_hacc) { + const size_t table_length = checked_table_length(padded_dim); + const size_t copies = use_hacc ? 2 : 1; + if (table_length > std::numeric_limits::max() / copies) { + throw std::length_error("FastScan lookup table is too large"); + } + return table_length * copies; + } + size_t table_length_ = 0; std::vector lut_; - T delta_; - T sum_vl_lut_; + T delta_ = 0; + T sum_vl_lut_ = 0; public: explicit Lut() = default; explicit Lut(const T* rotated_query, size_t padded_dim, bool use_hacc = false) - : table_length_(padded_dim << 2) - , lut_(table_length_ * (static_cast(use_hacc) + 1)) { + : table_length_(checked_table_length(padded_dim)) + , lut_(checked_storage_length(padded_dim, use_hacc)) { // quantize float lut std::vector lut_float(table_length_); fastscan::pack_lut(padded_dim, rotated_query, lut_float.data()); @@ -53,13 +75,6 @@ class Lut { size_t num_table = table_length_ / 16; sum_vl_lut_ = vl_lut * static_cast(num_table); } - Lut& operator=(Lut&& other) noexcept { - lut_ = std::move(other.lut_); - delta_ = other.delta_; - sum_vl_lut_ = other.sum_vl_lut_; - return *this; - } - [[nodiscard]] const uint8_t* lut() const { return lut_.data(); }; [[nodiscard]] T delta() const { return delta_; }; [[nodiscard]] T sum_vl() const { return sum_vl_lut_; }; diff --git a/include/rabitqlib/index/query.hpp b/include/rabitqlib/index/query.hpp index c5c6a38..3440d76 100644 --- a/include/rabitqlib/index/query.hpp +++ b/include/rabitqlib/index/query.hpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include "rabitqlib/defines.hpp" @@ -28,9 +27,7 @@ class BatchQuery { explicit BatchQuery( const T* rotated_query, size_t padded_dim, MetricType metric_type = METRIC_L2 ) - : metric_type_(metric_type) { - lookup_table_ = std::move(Lut(rotated_query, padded_dim)); - + : lookup_table_(rotated_query, padded_dim), metric_type_(metric_type) { float c_1 = -((1 << 1) - 1) / 2.F; T sumq = @@ -74,11 +71,9 @@ class SplitBatchQuery { MetricType metric_type = METRIC_L2, bool use_hacc = true ) - : rotated_query_(rotated_query) { - lookup_table_ = std::move(Lut(rotated_query, padded_dim, use_hacc)); - - metric_type_ = (metric_type == METRIC_IP) ? METRIC_IP : METRIC_L2; - + : rotated_query_(rotated_query) + , lookup_table_(rotated_query, padded_dim, use_hacc) + , metric_type_((metric_type == METRIC_IP) ? METRIC_IP : METRIC_L2) { float c_1 = -static_cast((1 << 1) - 1) / 2.F; float c_b = -static_cast((1 << (ex_bits + 1)) - 1) / 2.F; T sumq = diff --git a/include/rabitqlib/index/symqg/detail/pipnn.hpp b/include/rabitqlib/index/symqg/detail/pipnn.hpp index 51a3fb1..eb93fe2 100644 --- a/include/rabitqlib/index/symqg/detail/pipnn.hpp +++ b/include/rabitqlib/index/symqg/detail/pipnn.hpp @@ -303,8 +303,6 @@ inline InitialGraph build_initial_graph( } using namespace pipnn_impl; const size_t threads = std::max(1, std::min(num_threads, total_threads())); - // Match QGBuilder's thread setting, including Eigen when threads == 1. - omp_set_num_threads(static_cast(threads)); ScratchPool scratch(count, dim, threads); auto leaves = cluster(data, count, dim, metric, threads, scratch); RowMajorMatrix projections(dim, kHashBits); diff --git a/include/rabitqlib/index/symqg/qg.hpp b/include/rabitqlib/index/symqg/qg.hpp index 73da6a0..2dcbdbd 100644 --- a/include/rabitqlib/index/symqg/qg.hpp +++ b/include/rabitqlib/index/symqg/qg.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -22,7 +23,6 @@ #include "rabitqlib/quantization/data_layout.hpp" #include "rabitqlib/quantization/pack_excode.hpp" #include "rabitqlib/quantization/rabitq.hpp" -#include "rabitqlib/utils/array.hpp" #include "rabitqlib/utils/buffer.hpp" #include "rabitqlib/utils/io.hpp" #include "rabitqlib/utils/memory.hpp" @@ -65,26 +65,24 @@ class QuantizedGraph { friend struct QGConstructionTestAccess; private: - size_t num_points_ = 0; // num points - size_t degree_bound_ = 0; // degree bound - size_t dim_ = 0; // dimension - size_t padded_dim_ = 0; // padded dimension - T (*raw_dist_func_)(const T*, const T*, size_t); // dist func for raw vector - PID entry_point_ = 0; // Entry point of graph + size_t num_points_ = 0; // num points + size_t degree_bound_ = 0; // degree bound + size_t dim_ = 0; // dimension + size_t padded_dim_ = 0; // padded dimension + T (*raw_dist_func_)(const T*, const T*, size_t) = nullptr; // raw-vector distance + PID entry_point_ = 0; // Entry point of graph MetricType metric_type_ = MetricType::METRIC_L2; RotatorType rotator_type_ = RotatorType::FhtKacRotator; size_t quantization_bits_ = 0; // 0: raw vectors, 4/8: packed RaBitQ vectors std::vector centroid_; // rotated global centroid for qg-quant ex_ipfunc quantized_ip_func_ = nullptr; - Array< - char, - std::vector, - memory::AlignedAllocator< - char, - 1 << 22, - true>> - data_; // vectors/codes + graph quantization data + edges + using RowStorage = std::vector>; + // Complete rows are contiguous in both raw and quantized modes: + // vector/code, neighbor quantization data, then packed neighbor IDs. + // Typed storage establishes T lifetimes for raw vectors; packed portions + // are accessed only as bytes, never as T values. + RowStorage data_; std::unique_ptr> rotator_; // data rotator // Position of row data (raw vector or packed qg-quant vector), neighbor @@ -94,29 +92,56 @@ class QuantizedGraph { size_t neighbor_offset_ = 0; // offset of neighbors size_t row_offset_ = 0; // length of entire row size_t ef_ = 0; + bool ready_ = false; + + [[nodiscard]] static size_t checked_add(size_t lhs, size_t rhs) { + if (lhs > std::numeric_limits::max() - rhs) { + throw std::length_error("QuantizedGraph storage size exceeds size_t"); + } + return lhs + rhs; + } + + [[nodiscard]] static size_t checked_multiply(size_t lhs, size_t rhs) { + if (lhs != 0 && rhs > std::numeric_limits::max() / lhs) { + throw std::length_error("QuantizedGraph storage size exceeds size_t"); + } + return lhs * rhs; + } + + [[nodiscard]] static size_t padded_dimension(size_t dim) { + return (checked_add(dim, 63) / 64) * 64; + } void validate_configuration() const; + void initialize_layout(); + void initialize(); - void copy_vectors(const T*); + void copy_vectors(const T*, size_t); void set_quantization_centroid(const T* centroid); + [[nodiscard]] char* get_row_data(PID data_id) { + return reinterpret_cast(get_vector(data_id)); + } + + [[nodiscard]] const char* get_row_data(PID data_id) const { + return reinterpret_cast(get_vector(data_id)); + } + [[nodiscard]] T* get_vector(PID data_id) { - return reinterpret_cast(&data_.at(row_offset_ * data_id)); + return data_.data() + ((row_offset_ / sizeof(T)) * data_id); } [[nodiscard]] const T* get_vector(PID data_id) const { - return reinterpret_cast(&data_.at(row_offset_ * data_id)); + return data_.data() + ((row_offset_ / sizeof(T)) * data_id); } - [[nodiscard]] char* get_quantized_vector(PID data_id) { - return &data_.at(row_offset_ * data_id); - } + [[nodiscard]] char* get_quantized_vector(PID data_id) { return get_row_data(data_id); } [[nodiscard]] const char* get_quantized_vector(PID data_id) const { - return &data_.at(row_offset_ * data_id); + return get_row_data(data_id); } void prepare_query(const T*, std::vector&, std::optional>&) const; @@ -131,21 +156,23 @@ class QuantizedGraph { void reconstruct_quantized_vector(PID, T*) const; [[nodiscard]] char* get_batch_data(PID data_id) { - return &data_.at((row_offset_ * data_id) + batch_data_offset_); + return get_row_data(data_id) + batch_data_offset_; } [[nodiscard]] const char* get_batch_data(PID data_id) const { - return &data_.at((row_offset_ * data_id) + batch_data_offset_); + return get_row_data(data_id) + batch_data_offset_; } - [[nodiscard]] PID* get_neighbors(PID data_id) { - return reinterpret_cast(&data_.at((row_offset_ * data_id) + neighbor_offset_) + [[nodiscard]] rabitqlib::detail::PackedArrayView get_neighbors(PID data_id) { + return rabitqlib::detail::PackedArrayView( + get_row_data(data_id) + neighbor_offset_ ); } - [[nodiscard]] const PID* get_neighbors(PID data_id) const { - return reinterpret_cast( - &data_.at((row_offset_ * data_id) + neighbor_offset_) + [[nodiscard]] rabitqlib::detail::ConstPackedArrayView get_neighbors(PID data_id + ) const { + return rabitqlib::detail::ConstPackedArrayView( + get_row_data(data_id) + neighbor_offset_ ); } @@ -176,6 +203,11 @@ class QuantizedGraph { ~QuantizedGraph() = default; + QuantizedGraph(const QuantizedGraph&) = delete; + QuantizedGraph& operator=(const QuantizedGraph&) = delete; + QuantizedGraph(QuantizedGraph&&) noexcept = default; + QuantizedGraph& operator=(QuantizedGraph&&) noexcept = default; + [[nodiscard]] auto num_vertices() const { return this->num_points_; } [[nodiscard]] auto dimension() const { return this->dim_; } @@ -190,7 +222,12 @@ class QuantizedGraph { [[nodiscard]] bool is_quantized() const { return quantization_bits_ != 0; } - void set_ep(PID entry) { this->entry_point_ = entry; }; + void set_ep(PID entry) { + if (entry >= num_points_) { + throw std::invalid_argument("QuantizedGraph entry point is out of range"); + } + entry_point_ = entry; + } void save(const char*) const; @@ -231,6 +268,13 @@ inline QuantizedGraph::QuantizedGraph( template inline void QuantizedGraph::validate_configuration() const { validate_metric_type(metric_type_); + if (dim_ == 0) { + throw std::invalid_argument("QuantizedGraph dimension must be positive"); + } + if (rotator_type_ != RotatorType::MatrixRotator && + rotator_type_ != RotatorType::FhtKacRotator) { + throw std::invalid_argument("QuantizedGraph rotator type is invalid"); + } if (degree_bound_ == 0 || degree_bound_ % fastscan::kBatchSize != 0) { throw std::invalid_argument( "QuantizedGraph degree bound must be a positive multiple of 32" @@ -246,6 +290,9 @@ inline void QuantizedGraph::validate_configuration() const { "QuantizedGraph point count exceeds the search-buffer ID limit" ); } + if (entry_point_ >= num_points_) { + throw std::invalid_argument("QuantizedGraph entry point is out of range"); + } if (quantization_bits_ != 0 && quantization_bits_ != 4 && quantization_bits_ != 8) { throw std::invalid_argument( "QuantizedGraph quantization bits must be 0 (vanilla), 4, or 8" @@ -258,7 +305,8 @@ inline void QuantizedGraph::validate_configuration() const { } template -inline void QuantizedGraph::copy_vectors(const T* data) { +inline void QuantizedGraph::copy_vectors(const T* data, size_t num_threads) { + const int thread_count = static_cast(num_threads); if (quantization_bits_ != 0) { if constexpr (!std::is_same_v) { throw std::logic_error("qg-quant currently requires float data"); @@ -268,7 +316,7 @@ inline void QuantizedGraph::copy_vectors(const T* data) { "qg-quant centroid must be set before copying vectors" ); } -#pragma omp parallel +#pragma omp parallel num_threads(thread_count) { std::vector rotated_data(padded_dim_); std::vector quantized_data(padded_dim_); @@ -278,6 +326,8 @@ inline void QuantizedGraph::copy_vectors(const T* data) { ExDataMap output( get_quantized_vector(i), padded_dim_, quantization_bits_ ); + T f_add; + T f_rescale; T unused_f_error = 0; quant::quantize_full_single( rotated_data.data(), @@ -285,11 +335,13 @@ inline void QuantizedGraph::copy_vectors(const T* data) { padded_dim_, quantization_bits_, quantized_data.data(), - output.f_add_ex(), - output.f_rescale_ex(), + f_add, + f_rescale, unused_f_error, metric_type_ ); + output.f_add_ex() = f_add; + output.f_rescale_ex() = f_rescale; quant::rabitq_impl::ex_bits::packing_rabitqplus_code( quantized_data.data(), output.ex_code(), @@ -301,7 +353,7 @@ inline void QuantizedGraph::copy_vectors(const T* data) { return; } } -#pragma omp parallel for schedule(dynamic) +#pragma omp parallel for schedule(dynamic) num_threads(thread_count) for (size_t i = 0; i < num_points_; ++i) { const T* src = data + (dim_ * i); T* dst = get_vector(i); @@ -320,10 +372,17 @@ inline void QuantizedGraph::set_quantization_centroid(const T* centroid) { template inline void QuantizedGraph::save(const char* filename) const { + if (!ready_ || rotator_ == nullptr) { + throw std::logic_error("QuantizedGraph must be built or loaded before save"); + } + if (filename == nullptr || filename[0] == '\0') { + throw std::invalid_argument("QuantizedGraph save filename must not be empty"); + } std::ofstream output(filename, std::ios::binary); if (!output.is_open()) { throw std::runtime_error("Cannot open quantized graph file for writing"); } + output.exceptions(std::ios::badbit | std::ios::failbit); constexpr uint64_t kFormatMagic = 0x5147524142495451ULL; // "QGRABITQ" constexpr uint32_t kFormatVersion = 1; @@ -352,16 +411,23 @@ inline void QuantizedGraph::save(const char* filename) const { } /* Data */ - data_.save(output); + output.write( + get_row_data(0), + static_cast(checked_multiply(num_points_, row_offset_)) + ); /* Rotator */ this->rotator_->save(output); + output.flush(); output.close(); } template inline void QuantizedGraph::load(const char* filename) { + if (filename == nullptr || filename[0] == '\0') { + throw std::invalid_argument("QuantizedGraph load filename must not be empty"); + } /* Check existence */ if (!file_exists(filename)) { throw std::runtime_error("Quantized graph file does not exist"); @@ -372,13 +438,30 @@ inline void QuantizedGraph::load(const char* filename) { throw std::runtime_error("Cannot open quantized graph file"); } + auto read_exact = [&](void* destination, size_t bytes, const char* field) { + if (bytes > static_cast(std::numeric_limits::max())) { + throw std::runtime_error("QuantizedGraph field is too large to read"); + } + input.read( + reinterpret_cast(destination), static_cast(bytes) + ); + if (!input) { + throw std::runtime_error( + std::string("Truncated QuantizedGraph file while reading ") + field + ); + } + }; + auto read_value = [&](auto& value, const char* field) { + read_exact(&value, sizeof(value), field); + }; + constexpr uint64_t kFormatMagic = 0x5147524142495451ULL; // "QGRABITQ" constexpr uint32_t kFormatVersion = 1; uint64_t magic = 0; - input.read(reinterpret_cast(&magic), sizeof(magic)); + read_value(magic, "format marker"); if (magic == kFormatMagic) { uint32_t version = 0; - input.read(reinterpret_cast(&version), sizeof(version)); + read_value(version, "format version"); if (version != kFormatVersion) { throw std::runtime_error("Unsupported QuantizedGraph file version"); } @@ -388,46 +471,88 @@ inline void QuantizedGraph::load(const char* filename) { input.seekg(0); } - /* Basic variants */ - input.read(reinterpret_cast(&num_points_), sizeof(size_t)); - input.read(reinterpret_cast(°ree_bound_), sizeof(size_t)); - input.read(reinterpret_cast(&dim_), sizeof(size_t)); - input.read(reinterpret_cast(&padded_dim_), sizeof(size_t)); - input.read(reinterpret_cast(&entry_point_), sizeof(PID)); - input.read(reinterpret_cast(&rotator_type_), sizeof(RotatorType)); - input.read(reinterpret_cast(&metric_type_), sizeof(MetricType)); + QuantizedGraph loaded; + size_t stored_padded_dim = 0; + read_value(loaded.num_points_, "point count"); + read_value(loaded.degree_bound_, "degree bound"); + read_value(loaded.dim_, "dimension"); + read_value(stored_padded_dim, "padded dimension"); + read_value(loaded.entry_point_, "entry point"); + read_value(loaded.rotator_type_, "rotator type"); + read_value(loaded.metric_type_, "metric type"); if (magic == kFormatMagic) { - input.read( - reinterpret_cast(&quantization_bits_), sizeof(quantization_bits_) - ); + read_value(loaded.quantization_bits_, "quantization bits"); } else { - quantization_bits_ = 0; + loaded.quantization_bits_ = 0; } - raw_dist_func_ = (metric_type_ == METRIC_IP) ? dot_product_dis : euclidean_sqr; + loaded.raw_dist_func_ = + (loaded.metric_type_ == METRIC_IP) ? dot_product_dis : euclidean_sqr; + loaded.validate_configuration(); + loaded.padded_dim_ = padded_dimension(loaded.dim_); + if (stored_padded_dim != loaded.padded_dim_) { + throw std::runtime_error("Invalid padded dimension in quantized graph file"); + } + loaded.initialize_layout(); - validate_configuration(); - initialize(); + const size_t centroid_bytes = loaded.quantization_bits_ == 0 + ? 0 + : checked_multiply(loaded.padded_dim_, sizeof(T)); + const size_t data_bytes = checked_multiply(loaded.num_points_, loaded.row_offset_); + const size_t rotator_bytes = + loaded.rotator_type_ == RotatorType::MatrixRotator + ? checked_multiply(checked_multiply(sizeof(T), loaded.dim_), loaded.padded_dim_) + : checked_multiply(loaded.padded_dim_, size_t{4}) / 8; + const size_t expected_payload_bytes = + checked_add(checked_add(centroid_bytes, data_bytes), rotator_bytes); - if (quantization_bits_ != 0) { - centroid_.resize(padded_dim_); - input.read(reinterpret_cast(centroid_.data()), padded_dim_ * sizeof(T)); + const auto payload_position = input.tellg(); + if (payload_position < 0) { + throw std::runtime_error("Cannot determine QuantizedGraph payload position"); + } + const size_t file_size = get_filesize(filename); + const size_t payload_offset = static_cast(payload_position); + if (payload_offset > file_size || + file_size - payload_offset != expected_payload_bytes) { + throw std::runtime_error("Invalid QuantizedGraph payload size"); } - /* Data */ - data_.load(input); + loaded.initialize(); - /* Rotator */ - this->rotator_->load(input); - if (rotator_->size() != padded_dim_) { - throw std::runtime_error("Invalid padded dimension in quantized graph file"); + if (loaded.quantization_bits_ != 0) { + loaded.centroid_.resize(loaded.padded_dim_); + read_exact(loaded.centroid_.data(), centroid_bytes, "quantization centroid"); + } + + read_exact(loaded.get_row_data(0), data_bytes, "graph data"); + + for (PID source = 0; source < loaded.num_points_; ++source) { + const auto neighbors = loaded.get_neighbors(source); + for (size_t i = 0; i < loaded.degree_bound_; ++i) { + if (neighbors[i] >= loaded.num_points_) { + throw std::runtime_error("Invalid QuantizedGraph neighbor ID"); + } + } + } + + loaded.rotator_->load(input); + if (!input) { + throw std::runtime_error("Truncated QuantizedGraph file while reading rotator"); } input.close(); + // ef is a runtime search setting rather than persisted index state. Preserve + // the target object's value, matching the previous in-place load behavior. + loaded.ef_ = ef_; + loaded.ready_ = true; + *this = std::move(loaded); } template inline void QuantizedGraph::set_ef(size_t cur_ef) { + if (cur_ef == 0) { + throw std::invalid_argument("QuantizedGraph ef must be positive"); + } this->ef_ = cur_ef; } @@ -438,6 +563,19 @@ inline void QuantizedGraph::search( uint32_t* __restrict__ results, T* __restrict__ dists ) { + if (!ready_ || rotator_ == nullptr) { + throw std::logic_error("QuantizedGraph must be built or loaded before search"); + } + if (query == nullptr || results == nullptr || dists == nullptr) { + throw std::invalid_argument("QuantizedGraph search buffers must not be null"); + } + if (k == 0 || k > num_points_) { + throw std::invalid_argument("QuantizedGraph k must be between 1 and num_points"); + } + if (ef_ < k) { + throw std::invalid_argument("QuantizedGraph ef must be at least k"); + } + std::vector rotated_query(padded_dim_); std::optional> quantized_query; prepare_query(query, rotated_query, quantized_query); @@ -477,6 +615,9 @@ inline void QuantizedGraph::search( } update_results(res_pool, *vis, query, quantized_query ? &*quantized_query : nullptr); + if (res_pool.size() != k) { + throw std::runtime_error("QuantizedGraph search could not produce k results"); + } res_pool.copy_results(results, dists); } @@ -522,7 +663,7 @@ void QuantizedGraph::scan_neighbors( batch_data += QGBatchDataMap::data_bytes(padded_dim_); } - const PID* ptr_nb = get_neighbors(data_id); + const auto neighbors = get_neighbors(data_id); for (size_t begin = 0; begin < cur_degree; begin += fastscan::kBatchSize) { const T threshold = search_pool.top_dist(); uint32_t candidate_mask = 0; @@ -541,16 +682,14 @@ void QuantizedGraph::scan_neighbors( const auto lane = static_cast(__builtin_ctz(candidate_mask)); candidate_mask &= candidate_mask - 1; const size_t i = begin + lane; - PID cur_neighbor = ptr_nb[i]; + PID cur_neighbor = neighbors[i]; T dist = est_dist[i]; if (search_pool.is_full(dist) || vis.get(cur_neighbor)) { continue; } search_pool.insert(cur_neighbor, dist); // update search buffer - memory::mem_prefetch_l2( - reinterpret_cast(get_vector(search_pool.next_id())), 10 - ); + memory::mem_prefetch_l2(get_row_data(search_pool.next_id()), 10); } } } @@ -566,11 +705,14 @@ inline void QuantizedGraph::update_results( return; } - auto data = result_pool.data(); - for (auto record : data) { - PID* ptr_nb = get_neighbors(record.id); + const auto& pool_data = result_pool.data(); + const std::vector> data( + pool_data.begin(), pool_data.begin() + static_cast(result_pool.size()) + ); + for (const auto& record : data) { + auto neighbors = get_neighbors(record.id); for (uint32_t i = 0; i < this->degree_bound_; ++i) { - PID cur_neighbor = ptr_nb[i]; + PID cur_neighbor = neighbors[i]; if (!vis.get(cur_neighbor)) { vis.set(cur_neighbor); result_pool.insert( @@ -586,27 +728,40 @@ inline void QuantizedGraph::update_results( // initialize const offsets & data array template -inline void QuantizedGraph::initialize() { - rotator_.reset( - choose_rotator(dim_, rotator_type_, round_up_to_multiple(dim_, 64)) +inline void QuantizedGraph::initialize_layout() { + if (quantization_bits_ == 0) { + batch_data_offset_ = checked_multiply(dim_, sizeof(T)); + } else { + const size_t code_bits = checked_multiply(padded_dim_, quantization_bits_); + batch_data_offset_ = checked_add(code_bits / 8, checked_multiply(sizeof(T), 2)); + } + + const size_t binary_batch_bytes = + checked_multiply(padded_dim_, fastscan::kBatchSize) / 8; + const size_t factor_bytes = + checked_multiply(checked_multiply(sizeof(T), fastscan::kBatchSize), size_t{2}); + const size_t batch_bytes = checked_add(binary_batch_bytes, factor_bytes); + neighbor_offset_ = checked_add( + batch_data_offset_, + checked_multiply(batch_bytes, degree_bound_ / fastscan::kBatchSize) ); - padded_dim_ = rotator_->size(); + row_offset_ = + checked_add(neighbor_offset_, checked_multiply(degree_bound_, sizeof(PID))); +} + +template +inline void QuantizedGraph::initialize() { + padded_dim_ = padded_dimension(dim_); + rotator_.reset(choose_rotator(dim_, rotator_type_, padded_dim_)); - /* check size */ assert(padded_dim_ % 64 == 0); assert(padded_dim_ >= dim_); - this->batch_data_offset_ = - quantization_bits_ == 0 ? dim_ * sizeof(T) - : ExDataMap::data_bytes(padded_dim_, quantization_bits_); - this->neighbor_offset_ = - batch_data_offset_ + (QGBatchDataMap::data_bytes(padded_dim_) * - (degree_bound_ / fastscan::kBatchSize)); - this->row_offset_ = neighbor_offset_ + (degree_bound_ * sizeof(PID)); + initialize_layout(); - data_ = Array, memory::AlignedAllocator>( - std::vector{num_points_, row_offset_} - ); + const size_t data_bytes = checked_multiply(num_points_, row_offset_); + assert(row_offset_ % sizeof(T) == 0); + data_ = RowStorage(data_bytes / sizeof(T)); if (quantization_bits_ != 0) { quantized_ip_func_ = select_excode_ipfunc(quantization_bits_); @@ -732,9 +887,9 @@ inline void QuantizedGraph::update_qg( return; } // copy neighbors - PID* neighbor_ptr = get_neighbors(cur_id); + auto neighbors = get_neighbors(cur_id); for (size_t i = 0; i < cur_degree; ++i) { - neighbor_ptr[i] = new_neighbors[i].id; + neighbors[i] = new_neighbors[i].id; } // rotated data @@ -758,18 +913,30 @@ inline void QuantizedGraph::update_qg( // quantize batches for current vertex auto* batch_data = get_batch_data(cur_id); - const auto* data = rotated_data.data(); for (size_t i = 0; i < cur_degree; i += fastscan::kBatchSize) { + const size_t batch_size = std::min(cur_degree - i, fastscan::kBatchSize); quant::quantize_qg_batch( - data, + rotated_data.data() + (i * padded_dim_), rotated_centroid.data(), - std::min(cur_degree - i, fastscan::kBatchSize), + batch_size, padded_dim_, batch_data, metric_type_ ); + if (batch_size < fastscan::kBatchSize) { + QGBatchDataMap batch(batch_data, padded_dim_); + std::fill( + batch.f_add() + batch_size, + batch.f_add() + fastscan::kBatchSize, + static_cast(0) + ); + std::fill( + batch.f_rescale() + batch_size, + batch.f_rescale() + fastscan::kBatchSize, + static_cast(0) + ); + } - data += fastscan::kBatchSize * padded_dim_; batch_data += QGBatchDataMap::data_bytes(padded_dim_); } } diff --git a/include/rabitqlib/index/symqg/qg_builder.hpp b/include/rabitqlib/index/symqg/qg_builder.hpp index c2e78d4..80f63cc 100644 --- a/include/rabitqlib/index/symqg/qg_builder.hpp +++ b/include/rabitqlib/index/symqg/qg_builder.hpp @@ -65,9 +65,7 @@ class QGBuilder { , num_threads_{std::max(1, std::min(num_threads, total_threads()))} , num_nodes_{qg_.num_vertices()} , dim_{qg_.dimension()} - , degree_bound_(qg_.degree_bound()) { - omp_set_num_threads(static_cast(num_threads_)); - } + , degree_bound_(qg_.degree_bound()) {} public: explicit QGBuilder( @@ -78,6 +76,12 @@ class QGBuilder { QGInitialization init = QGInitialization::PiPNN ) : QGBuilder(index, ef_build, num_threads) { + if (data == nullptr) { + throw std::invalid_argument("QGBuilder data must not be null"); + } + if (init != QGInitialization::PiPNN && init != QGInitialization::Random) { + throw std::invalid_argument("Unknown QG initialization"); + } if (init == QGInitialization::PiPNN) { auto seed = detail::build_initial_graph( data, num_nodes_, dim_, degree_bound_, qg_.metric_type_, num_threads_ @@ -87,8 +91,6 @@ class QGBuilder { seeded_ = false; initialize_storage(data); random_init(); - } else { - throw std::invalid_argument("Unknown QG initialization"); } } @@ -118,7 +120,7 @@ class QGBuilder { } } initialize_storage(data); -#pragma omp parallel +#pragma omp parallel num_threads(num_threads_) { CandidateList row; row.reserve(degree_bound_); @@ -147,7 +149,11 @@ class QGBuilder { public: // One complete search/prune/reverse-edge/degree-completion iteration. Call // before serving a seeded graph: search() requires full final rows. - void refine() { iter(true); } + void refine() { + qg_.ready_ = false; + iter(true); + qg_.ready_ = true; + } // One refinement for PiPNN initialization, three passes for random init. void build() { @@ -164,16 +170,18 @@ class QGBuilder { "The number of QG build iterations must be at least 2" ); } + qg_.ready_ = false; // for first iterations, we do not need to refine the graph structure for (size_t i = 0; i < num_iter - 1; ++i) { iter(false); } iter(true); + qg_.ready_ = true; } [[nodiscard]] bool check_dup() const { std::atomic flag(false); -#pragma omp parallel for +#pragma omp parallel for num_threads(num_threads_) for (size_t i = 0; i < num_nodes_; ++i) { std::unordered_set edges; for (auto nei : new_neighbors_[i]) { @@ -193,6 +201,9 @@ class QGBuilder { }; inline void QGBuilder::initialize_storage(const float* data) { + if (data == nullptr) { + throw std::invalid_argument("QGBuilder data must not be null"); + } // Allocate refinement scratch only after PiPNN's dense workspace is released. new_neighbors_.resize(num_nodes_); pruned_neighbors_.resize(num_nodes_); @@ -203,8 +214,9 @@ inline void QGBuilder::initialize_storage(const float* data) { degrees_.assign(num_nodes_, degree_bound_); std::vector centroid = compute_centroid(data, num_nodes_, dim_, num_threads_); + qg_.ready_ = false; qg_.set_quantization_centroid(centroid.data()); - qg_.copy_vectors(data); + qg_.copy_vectors(data, num_threads_); PID entry_point = 0; if (qg_.is_quantized()) { @@ -345,7 +357,7 @@ inline void QGBuilder::heuristic_prune( * @param refine refine = true means recording pruned candidates */ inline void QGBuilder::search_new_neighbors(bool refine) { -#pragma omp parallel for schedule(dynamic) +#pragma omp parallel for schedule(dynamic) num_threads(num_threads_) for (size_t i = 0; i < num_nodes_; ++i) { PID cur_id = i; auto tid = omp_get_thread_num(); @@ -361,7 +373,7 @@ inline void QGBuilder::search_new_neighbors(bool refine) { std::vector reconstructed; std::optional> prepared; const float* source = qg_.prepare_build_query(cur_id, reconstructed, prepared); - const PID* ids = qg_.get_neighbors(cur_id); + const auto ids = qg_.get_neighbors(cur_id); for (size_t j = 0; j < degrees_[cur_id]; ++j) { if (ids[j] != cur_id && !vis.get(ids[j])) { candidates.emplace_back( @@ -400,7 +412,7 @@ inline void QGBuilder::add_reverse_edges(bool refine) { // Keep new_neighbors_ read-only while reverse candidates are collected. Mutating a // destination row here races with another worker reading that row as its source. -#pragma omp parallel for schedule(dynamic) +#pragma omp parallel for schedule(dynamic) num_threads(num_threads_) for (PID data_id = 0; data_id < num_nodes_; ++data_id) { for (const auto& nei : new_neighbors_[data_id]) { const PID destination = nei.id; @@ -426,7 +438,7 @@ inline void QGBuilder::add_reverse_edges(bool refine) { } } -#pragma omp parallel for schedule(dynamic) +#pragma omp parallel for schedule(dynamic) num_threads(num_threads_) for (PID data_id = 0; data_id < num_nodes_; ++data_id) { CandidateList& tmp_pool = reverse_buffer[data_id]; if (qg_.is_quantized() && !tmp_pool.empty()) { @@ -450,7 +462,7 @@ inline void QGBuilder::add_reverse_edges(bool refine) { inline void QGBuilder::random_init() { const PID min_id = 0; const PID max_id = num_nodes_ - 1; -#pragma omp parallel for schedule(dynamic) +#pragma omp parallel for schedule(dynamic) num_threads(num_threads_) for (size_t i = 0; i < num_nodes_; ++i) { std::unordered_set neighbor_set; neighbor_set.reserve(degree_bound_); @@ -483,7 +495,7 @@ inline void QGBuilder::random_init() { * */ inline void QGBuilder::graph_refine() { -#pragma omp parallel for schedule(dynamic) +#pragma omp parallel for schedule(dynamic) num_threads(num_threads_) for (size_t i = 0; i < num_nodes_; ++i) { CandidateList& cur_neighbors = new_neighbors_[i]; size_t cur_degree = cur_neighbors.size(); @@ -560,7 +572,7 @@ inline void QGBuilder::iter(bool refine) { } // update qg -#pragma omp parallel for schedule(dynamic) +#pragma omp parallel for schedule(dynamic) num_threads(num_threads_) for (size_t i = 0; i < num_nodes_; ++i) { qg_.update_qg(i, new_neighbors_[i]); degrees_[i] = new_neighbors_[i].size(); diff --git a/include/rabitqlib/quantization/data_layout.hpp b/include/rabitqlib/quantization/data_layout.hpp index bc12905..15231b1 100644 --- a/include/rabitqlib/quantization/data_layout.hpp +++ b/include/rabitqlib/quantization/data_layout.hpp @@ -2,24 +2,169 @@ #include #include +#include +#include +#include #include "rabitqlib/fastscan/fastscan.hpp" namespace rabitqlib { +namespace detail { + +// Factor blocks are part of a packed byte layout and therefore need not be aligned for T. +// Access them through memcpy so the representation remains valid C++17 storage rather than +// manufacturing T objects inside a char buffer with reinterpret_cast. +template +class PackedValueRef { + static_assert( + std::is_trivially_copyable_v, "packed values must be trivially copyable" + ); + + public: + explicit PackedValueRef(char* data) : data_(data) {} + PackedValueRef(const PackedValueRef&) = default; + + PackedValueRef& operator=(T value) { + std::memcpy(data_, &value, sizeof(value)); + return *this; + } + + PackedValueRef& operator=(const PackedValueRef& other) { + return *this = static_cast(other); + } + + operator T() const { + T value; + std::memcpy(&value, data_, sizeof(value)); + return value; + } + + private: + char* data_; +}; + +template +class PackedArrayView { + static_assert( + std::is_trivially_copyable_v, "packed values must be trivially copyable" + ); + + public: + using difference_type = std::ptrdiff_t; + using value_type = T; + using pointer = void; + using reference = PackedValueRef; + using iterator_category = std::forward_iterator_tag; + + explicit PackedArrayView(char* data) : data_(data) {} + + [[nodiscard]] reference operator*() const { return reference(data_); } + [[nodiscard]] reference operator[](size_t index) const { + return reference(data_ + (index * sizeof(T))); + } + + PackedArrayView& operator++() { + data_ += sizeof(T); + return *this; + } + PackedArrayView operator++(int) { + PackedArrayView previous = *this; + ++*this; + return previous; + } + PackedArrayView& operator--() { + data_ -= sizeof(T); + return *this; + } + PackedArrayView& operator+=(difference_type count) { + data_ += count * static_cast(sizeof(T)); + return *this; + } + PackedArrayView& operator-=(difference_type count) { return *this += -count; } + + friend PackedArrayView operator+(PackedArrayView view, difference_type count) { + view += count; + return view; + } + friend PackedArrayView operator+(difference_type count, PackedArrayView view) { + return view + count; + } + friend PackedArrayView operator-(PackedArrayView view, difference_type count) { + view -= count; + return view; + } + friend difference_type operator-(PackedArrayView lhs, PackedArrayView rhs) { + return (lhs.data_ - rhs.data_) / static_cast(sizeof(T)); + } + friend bool operator==(PackedArrayView lhs, PackedArrayView rhs) { + return lhs.data_ == rhs.data_; + } + friend bool operator!=(PackedArrayView lhs, PackedArrayView rhs) { + return !(lhs == rhs); + } + + void copy_to(T* output, size_t count) const { + std::memcpy(output, data_, count * sizeof(T)); + } + + private: + char* data_; +}; + +template +class ConstPackedArrayView { + static_assert( + std::is_trivially_copyable_v, "packed values must be trivially copyable" + ); + + public: + explicit ConstPackedArrayView(const char* data) : data_(data) {} + + [[nodiscard]] T operator[](size_t index) const { + T value; + std::memcpy(&value, data_ + (index * sizeof(T)), sizeof(value)); + return value; + } + + void copy_to(T* output, size_t count) const { + std::memcpy(output, data_, count * sizeof(T)); + } + + private: + const char* data_; +}; + +template +[[nodiscard]] inline T load_packed_value(const char* data) { + static_assert( + std::is_trivially_copyable_v, "packed values must be trivially copyable" + ); + T value; + std::memcpy(&value, data, sizeof(value)); + return value; +} + +} // namespace detail + template struct BatchDataMap { public: explicit BatchDataMap(char* data, size_t padded_dim) : batch_bin_code_(reinterpret_cast(data)) - , f_add_(reinterpret_cast(data + (padded_dim * fastscan::kBatchSize / 8)) - ) // 1 bit code - , f_rescale_(f_add_ + fastscan::kBatchSize) - , f_error_(f_rescale_ + fastscan::kBatchSize) {} + , f_add_(data + (padded_dim * fastscan::kBatchSize / 8)) // 1 bit code + , f_rescale_( + data + (padded_dim * fastscan::kBatchSize / 8) + + (sizeof(T) * fastscan::kBatchSize) + ) + , f_error_( + data + (padded_dim * fastscan::kBatchSize / 8) + + (sizeof(T) * fastscan::kBatchSize * 2) + ) {} [[nodiscard]] uint8_t* bin_code() { return batch_bin_code_; } - [[nodiscard]] T* f_add() { return f_add_; } - [[nodiscard]] T* f_rescale() { return f_rescale_; } - [[nodiscard]] T* f_error() { return f_error_; } + [[nodiscard]] detail::PackedArrayView f_add() { return f_add_; } + [[nodiscard]] detail::PackedArrayView f_rescale() { return f_rescale_; } + [[nodiscard]] detail::PackedArrayView f_error() { return f_error_; } static size_t data_bytes(size_t padded_dim) { return (padded_dim * fastscan::kBatchSize / 8) + @@ -28,9 +173,9 @@ struct BatchDataMap { private: uint8_t* batch_bin_code_; - T* f_add_; - T* f_rescale_; - T* f_error_; + detail::PackedArrayView f_add_; + detail::PackedArrayView f_rescale_; + detail::PackedArrayView f_error_; }; template @@ -38,21 +183,26 @@ struct ConstBatchDataMap { public: explicit ConstBatchDataMap(const char* data, size_t padded_dim) : batch_bin_code_(reinterpret_cast(data)) - , f_add_(reinterpret_cast(data + (padded_dim * fastscan::kBatchSize / 8)) - ) // 1 bit code - , f_rescale_(f_add_ + fastscan::kBatchSize) - , f_error_(f_rescale_ + fastscan::kBatchSize) {} + , f_add_(data + (padded_dim * fastscan::kBatchSize / 8)) // 1 bit code + , f_rescale_( + data + (padded_dim * fastscan::kBatchSize / 8) + + (sizeof(T) * fastscan::kBatchSize) + ) + , f_error_( + data + (padded_dim * fastscan::kBatchSize / 8) + + (sizeof(T) * fastscan::kBatchSize * 2) + ) {} [[nodiscard]] const uint8_t* bin_code() const { return batch_bin_code_; } - [[nodiscard]] const T* f_add() const { return f_add_; } - [[nodiscard]] const T* f_rescale() const { return f_rescale_; } - [[nodiscard]] const T* f_error() const { return f_error_; } + [[nodiscard]] detail::ConstPackedArrayView f_add() const { return f_add_; } + [[nodiscard]] detail::ConstPackedArrayView f_rescale() const { return f_rescale_; } + [[nodiscard]] detail::ConstPackedArrayView f_error() const { return f_error_; } private: const uint8_t* batch_bin_code_; - const T* f_add_; - const T* f_rescale_; - const T* f_error_; + detail::ConstPackedArrayView f_add_; + detail::ConstPackedArrayView f_rescale_; + detail::ConstPackedArrayView f_error_; }; template @@ -60,13 +210,15 @@ struct QGBatchDataMap { public: explicit QGBatchDataMap(char* data, size_t padded_dim) : batch_bin_code_(reinterpret_cast(data)) - , f_add_(reinterpret_cast(data + (padded_dim * fastscan::kBatchSize / 8)) - ) // 1 bit code - , f_rescale_(f_add_ + fastscan::kBatchSize) {} + , f_add_(data + (padded_dim * fastscan::kBatchSize / 8)) // 1 bit code + , f_rescale_( + data + (padded_dim * fastscan::kBatchSize / 8) + + (sizeof(T) * fastscan::kBatchSize) + ) {} [[nodiscard]] uint8_t* bin_code() { return batch_bin_code_; } - [[nodiscard]] T* f_add() { return f_add_; } - [[nodiscard]] T* f_rescale() { return f_rescale_; } + [[nodiscard]] detail::PackedArrayView f_add() { return f_add_; } + [[nodiscard]] detail::PackedArrayView f_rescale() { return f_rescale_; } static size_t data_bytes(size_t padded_dim) { return (padded_dim * fastscan::kBatchSize / 8) + @@ -75,8 +227,8 @@ struct QGBatchDataMap { private: uint8_t* batch_bin_code_; - T* f_add_; - T* f_rescale_; + detail::PackedArrayView f_add_; + detail::PackedArrayView f_rescale_; }; template @@ -84,13 +236,15 @@ struct ConstQGBatchDataMap { public: explicit ConstQGBatchDataMap(const char* data, size_t padded_dim) : batch_bin_code_(reinterpret_cast(data)) - , f_add_(reinterpret_cast(data + (padded_dim * fastscan::kBatchSize / 8)) - ) // 1 bit code - , f_rescale_(f_add_ + fastscan::kBatchSize) {} + , f_add_(data + (padded_dim * fastscan::kBatchSize / 8)) // 1 bit code + , f_rescale_( + data + (padded_dim * fastscan::kBatchSize / 8) + + (sizeof(T) * fastscan::kBatchSize) + ) {} - [[nodiscard]] const uint8_t* bin_code() { return batch_bin_code_; } - [[nodiscard]] const T* f_add() { return f_add_; } - [[nodiscard]] const T* f_rescale() { return f_rescale_; } + [[nodiscard]] const uint8_t* bin_code() const { return batch_bin_code_; } + [[nodiscard]] detail::ConstPackedArrayView f_add() const { return f_add_; } + [[nodiscard]] detail::ConstPackedArrayView f_rescale() const { return f_rescale_; } static size_t data_bytes(size_t padded_dim) { return (padded_dim * fastscan::kBatchSize / 8) + @@ -99,8 +253,8 @@ struct ConstQGBatchDataMap { private: const uint8_t* batch_bin_code_; - const T* f_add_; - const T* f_rescale_; + detail::ConstPackedArrayView f_add_; + detail::ConstPackedArrayView f_rescale_; }; template @@ -108,21 +262,21 @@ struct ExDataMap { public: explicit ExDataMap(char* data, size_t padded_dim, size_t ex_bits) : ex_code_(reinterpret_cast(data)) - , f_add_ex_(*reinterpret_cast(data + (padded_dim * ex_bits / 8))) - , f_recale_ex_(*(reinterpret_cast(data + (padded_dim * ex_bits / 8)) + 1)) {} + , f_add_ex_(data + (padded_dim * ex_bits / 8)) + , f_recale_ex_(data + (padded_dim * ex_bits / 8) + sizeof(T)) {} static size_t data_bytes(size_t padded_dim, size_t ex_bits) { return ex_bits > 0 ? (padded_dim * ex_bits / 8) + (sizeof(T) * 2) : 0; } [[nodiscard]] uint8_t* ex_code() { return ex_code_; } - [[nodiscard]] T& f_add_ex() { return f_add_ex_; } - [[nodiscard]] T& f_rescale_ex() { return f_recale_ex_; } + [[nodiscard]] detail::PackedValueRef f_add_ex() { return f_add_ex_; } + [[nodiscard]] detail::PackedValueRef f_rescale_ex() { return f_recale_ex_; } private: uint8_t* ex_code_; - T& f_add_ex_; - T& f_recale_ex_; + detail::PackedValueRef f_add_ex_; + detail::PackedValueRef f_recale_ex_; }; template @@ -130,18 +284,19 @@ struct ConstExDataMap { public: explicit ConstExDataMap(const char* data, size_t padded_dim, size_t ex_bits) : ex_code_(reinterpret_cast(data)) - , f_add_ex_(*reinterpret_cast(data + (padded_dim * ex_bits / 8))) - , f_recale_ex_(*(reinterpret_cast(data + (padded_dim * ex_bits / 8)) + 1) - ) {} + , f_add_ex_(data + (padded_dim * ex_bits / 8)) + , f_recale_ex_(data + (padded_dim * ex_bits / 8) + sizeof(T)) {} [[nodiscard]] const uint8_t* ex_code() const { return ex_code_; } - [[nodiscard]] const T& f_add_ex() const { return f_add_ex_; } - [[nodiscard]] const T& f_rescale_ex() const { return f_recale_ex_; } + [[nodiscard]] T f_add_ex() const { return detail::load_packed_value(f_add_ex_); } + [[nodiscard]] T f_rescale_ex() const { + return detail::load_packed_value(f_recale_ex_); + } private: const uint8_t* ex_code_; - const T& f_add_ex_; - const T& f_recale_ex_; + const char* f_add_ex_; + const char* f_recale_ex_; }; template @@ -149,24 +304,24 @@ struct BaseDataMap { public: explicit BaseDataMap(char* data, size_t padded_dim, size_t base_bits) : base_code_(reinterpret_cast(data)) - , f_add_(*reinterpret_cast(data + (padded_dim * base_bits / 8))) - , f_rescale_(*(reinterpret_cast(data + (padded_dim * base_bits / 8)) + 1)) - , f_error_(*(reinterpret_cast(data + (padded_dim * base_bits / 8)) + 2)) {} + , f_add_(data + (padded_dim * base_bits / 8)) + , f_rescale_(data + (padded_dim * base_bits / 8) + sizeof(T)) + , f_error_(data + (padded_dim * base_bits / 8) + (sizeof(T) * 2)) {} static size_t data_bytes(size_t padded_dim, size_t base_bits) { return (padded_dim * base_bits / 8) + (sizeof(T) * 3); } [[nodiscard]] uint8_t* base_code() { return base_code_; } - [[nodiscard]] T& f_add() { return f_add_; } - [[nodiscard]] T& f_rescale() { return f_rescale_; } - [[nodiscard]] T& f_error() { return f_error_; } + [[nodiscard]] detail::PackedValueRef f_add() { return f_add_; } + [[nodiscard]] detail::PackedValueRef f_rescale() { return f_rescale_; } + [[nodiscard]] detail::PackedValueRef f_error() { return f_error_; } private: uint8_t* base_code_; - T& f_add_; - T& f_rescale_; - T& f_error_; + detail::PackedValueRef f_add_; + detail::PackedValueRef f_rescale_; + detail::PackedValueRef f_error_; }; template @@ -174,70 +329,69 @@ struct ConstBaseDataMap { public: explicit ConstBaseDataMap(const char* data, size_t padded_dim, size_t base_bits) : base_code_(reinterpret_cast(data)) - , f_add_(*reinterpret_cast(data + (padded_dim * base_bits / 8))) - , f_rescale_(*(reinterpret_cast(data + (padded_dim * base_bits / 8)) + 1)) - , f_error_(*(reinterpret_cast(data + (padded_dim * base_bits / 8)) + 2)) { - } + , f_add_(data + (padded_dim * base_bits / 8)) + , f_rescale_(data + (padded_dim * base_bits / 8) + sizeof(T)) + , f_error_(data + (padded_dim * base_bits / 8) + (sizeof(T) * 2)) {} [[nodiscard]] const uint8_t* base_code() const { return base_code_; } - [[nodiscard]] const T& f_add() const { return f_add_; } - [[nodiscard]] const T& f_rescale() const { return f_rescale_; } - [[nodiscard]] const T& f_error() const { return f_error_; } + [[nodiscard]] T f_add() const { return detail::load_packed_value(f_add_); } + [[nodiscard]] T f_rescale() const { return detail::load_packed_value(f_rescale_); } + [[nodiscard]] T f_error() const { return detail::load_packed_value(f_error_); } private: const uint8_t* base_code_; - const T& f_add_; - const T& f_rescale_; - const T& f_error_; + const char* f_add_; + const char* f_rescale_; + const char* f_error_; }; template struct BinDataMap { public: explicit BinDataMap(char* data, size_t padded_dim) - : bin_code_(reinterpret_cast(data)) - , f_add_(*reinterpret_cast(data + (padded_dim / 8))) - , f_rescale_(*(reinterpret_cast(data + (padded_dim / 8)) + 1)) - , f_error_(*(reinterpret_cast(data + (padded_dim / 8)) + 2)) {} + : bin_code_(reinterpret_cast(data)) + , f_add_(data + (padded_dim / 8)) + , f_rescale_(data + (padded_dim / 8) + sizeof(T)) + , f_error_(data + (padded_dim / 8) + (sizeof(T) * 2)) {} - [[nodiscard]] uint64_t* bin_code() { return bin_code_; } - [[nodiscard]] T& f_add() { return f_add_; } - [[nodiscard]] T& f_rescale() { return f_rescale_; } - [[nodiscard]] T& f_error() { return f_error_; } + [[nodiscard]] uint8_t* bin_code() { return bin_code_; } + [[nodiscard]] detail::PackedValueRef f_add() { return f_add_; } + [[nodiscard]] detail::PackedValueRef f_rescale() { return f_rescale_; } + [[nodiscard]] detail::PackedValueRef f_error() { return f_error_; } static size_t data_bytes(size_t padded_dim) { return (padded_dim / 8) + (sizeof(T) * 3); } private: - uint64_t* bin_code_; - T& f_add_; - T& f_rescale_; - T& f_error_; + uint8_t* bin_code_; + detail::PackedValueRef f_add_; + detail::PackedValueRef f_rescale_; + detail::PackedValueRef f_error_; }; template struct ConstBinDataMap { public: explicit ConstBinDataMap(const char* data, size_t padded_dim) - : bin_code_(reinterpret_cast(data)) - , f_add_(*reinterpret_cast(data + (padded_dim / 8))) - , f_rescale_(*(reinterpret_cast(data + (padded_dim / 8)) + 1)) - , f_error_(*(reinterpret_cast(data + (padded_dim / 8)) + 2)) {} + : bin_code_(reinterpret_cast(data)) + , f_add_(data + (padded_dim / 8)) + , f_rescale_(data + (padded_dim / 8) + sizeof(T)) + , f_error_(data + (padded_dim / 8) + (sizeof(T) * 2)) {} - [[nodiscard]] const uint64_t* bin_code() { return bin_code_; } - [[nodiscard]] const T& f_add() { return f_add_; } - [[nodiscard]] const T& f_rescale() { return f_rescale_; } - [[nodiscard]] const T& f_error() { return f_error_; } + [[nodiscard]] const uint8_t* bin_code() const { return bin_code_; } + [[nodiscard]] T f_add() const { return detail::load_packed_value(f_add_); } + [[nodiscard]] T f_rescale() const { return detail::load_packed_value(f_rescale_); } + [[nodiscard]] T f_error() const { return detail::load_packed_value(f_error_); } static size_t data_bytes(size_t padded_dim) { return (padded_dim / 8) + (sizeof(T) * 3); } private: - const uint64_t* bin_code_; - const T& f_add_; - const T& f_rescale_; - const T& f_error_; + const uint8_t* bin_code_; + const char* f_add_; + const char* f_rescale_; + const char* f_error_; }; -} // namespace rabitqlib \ No newline at end of file +} // namespace rabitqlib diff --git a/include/rabitqlib/quantization/rabitq.hpp b/include/rabitqlib/quantization/rabitq.hpp index f3ea9a6..5b4176f 100644 --- a/include/rabitqlib/quantization/rabitq.hpp +++ b/include/rabitqlib/quantization/rabitq.hpp @@ -137,17 +137,23 @@ inline void quantize_compact_one_bit( MetricType metric_type = METRIC_L2 ) { BinDataMap cur_bin_data(bin_data, padded_dim); + T f_add; + T f_rescale; + T f_error; - rabitq_impl::one_bit::one_bit_compact_code( + rabitq_impl::one_bit::one_bit_compact_code_to_bytes( data, centroid, padded_dim, cur_bin_data.bin_code(), - cur_bin_data.f_add(), - cur_bin_data.f_rescale(), - cur_bin_data.f_error(), + f_add, + f_rescale, + f_error, metric_type ); + cur_bin_data.f_add() = f_add; + cur_bin_data.f_rescale() = f_rescale; + cur_bin_data.f_error() = f_error; } template @@ -202,6 +208,8 @@ inline void quantize_compact_ex_bits( ExDataMap cur_ex_data(ex_data, padded_dim, ex_bits); // we do not use this error factor here + T f_add_ex; + T f_rescale_ex; T ex_error; rabitq_impl::ex_bits::ex_bits_compact_code( @@ -210,12 +218,14 @@ inline void quantize_compact_ex_bits( padded_dim, ex_bits, cur_ex_data.ex_code(), - cur_ex_data.f_add_ex(), - cur_ex_data.f_rescale_ex(), + f_add_ex, + f_rescale_ex, ex_error, metric_type, config.t_const ); + cur_ex_data.f_add_ex() = f_add_ex; + cur_ex_data.f_rescale_ex() = f_rescale_ex; } inline void quantize_split_batch( @@ -427,4 +437,4 @@ inline TF full_est_dist( return est_dist; } -} // namespace rabitqlib::quant \ No newline at end of file +} // namespace rabitqlib::quant diff --git a/include/rabitqlib/quantization/rabitq_impl.hpp b/include/rabitqlib/quantization/rabitq_impl.hpp index b0447da..2e2c1de 100644 --- a/include/rabitqlib/quantization/rabitq_impl.hpp +++ b/include/rabitqlib/quantization/rabitq_impl.hpp @@ -179,11 +179,11 @@ inline void one_bit_code_with_factor( * approximate distances between the original vectors. */ template -inline void one_bit_compact_code( +inline void one_bit_compact_code_to_bytes( const T* data, const T* centroid, size_t padded_dim, - TC* compact_code, + uint8_t* compact_code, T& f_add, T& f_recale, T& f_error, @@ -204,51 +204,91 @@ inline void one_bit_compact_code( metric_type ); - pack_binary(binary_code.data(), compact_code, padded_dim); + pack_binary_to_bytes(binary_code.data(), compact_code, padded_dim); +} + +template +inline void one_bit_compact_code( + const T* data, + const T* centroid, + size_t padded_dim, + TC* compact_code, + T& f_add, + T& f_recale, + T& f_error, + MetricType metric_type = METRIC_L2 +) { + one_bit_compact_code_to_bytes( + data, + centroid, + padded_dim, + reinterpret_cast(compact_code), + f_add, + f_recale, + f_error, + metric_type + ); } // Requires a positive padded_dim divisible by sizeof(TC) * 8. -template +template < + typename T, + typename TC, + bool Parallel = false, + typename FAdd, + typename FRescale, + typename FError> inline void one_bit_compact_codes( const T* data, const T* centroid, size_t num, size_t padded_dim, TC* compact_code, - T* f_add, - T* f_rescale, - T* f_error, + FAdd f_add, + FRescale f_rescale, + FError f_error, MetricType metric_type = METRIC_L2 ) { constexpr size_t kTypeBits = sizeof(TC) * 8; #pragma omp parallel for if (Parallel) for (size_t i = 0; i < num; ++i) { + T add; + T rescale; + T error; one_bit_compact_code( data + (padded_dim * i), centroid, padded_dim, compact_code + (padded_dim / kTypeBits * i), - f_add[i], - f_rescale[i], - f_error[i], + add, + rescale, + error, metric_type ); + f_add[i] = add; + f_rescale[i] = rescale; + f_error[i] = error; } } // Encoding requires a positive padded_dim divisible by 8; index pipelines use 64. // packed_code needs ceil(num / 32) * 32 * (padded_dim / 8) bytes, including tail padding. -template +template < + typename T, + bool Parallel = false, + typename FAdd, + typename FRescale, + typename FError> inline void one_bit_batch_code( const T* data, const T* centroid, size_t num, size_t padded_dim, uint8_t* packed_code, - T* f_add, - T* f_recale, - T* f_error, + FAdd f_add, + FRescale f_recale, + FError f_error, MetricType metric_type = METRIC_L2 ) { std::vector compact_codes(num * padded_dim / 8); @@ -873,17 +913,23 @@ inline void split_code_with_factor( // Base layer first: its factors describe the filter code on its own. BaseDataMap base_map(base_data, dim, base_bits); + T f_add_base; + T f_rescale_base; + T f_error_base; code_factors( residual, centroid, dim, base_code_int.data(), -(static_cast((1U << base_bits) - 1) / 2.F), - base_map.f_add(), - base_map.f_rescale(), - base_map.f_error(), + f_add_base, + f_rescale_base, + f_error_base, metric_type ); + base_map.f_add() = f_add_base; + base_map.f_rescale() = f_rescale_base; + base_map.f_error() = f_error_base; ex_bits::packing_rabitqplus_code(base_raw.data(), base_map.base_code(), dim, base_bits); if (ex_bits == 0) { @@ -892,6 +938,8 @@ inline void split_code_with_factor( // Refine layer: the same derivation over the combined code. ExDataMap ex_map(ex_data, dim, ex_bits); + T f_add_ex; + T f_rescale_ex; T f_error_ex = 0; code_factors( residual, @@ -899,11 +947,13 @@ inline void split_code_with_factor( dim, total_code.data(), -(static_cast((1U << total_bits) - 1) / 2.F), - ex_map.f_add_ex(), - ex_map.f_rescale_ex(), + f_add_ex, + f_rescale_ex, f_error_ex, metric_type ); + ex_map.f_add_ex() = f_add_ex; + ex_map.f_rescale_ex() = f_rescale_ex; ex_bits::packing_rabitqplus_code(ex_raw.data(), ex_map.ex_code(), dim, ex_bits); } diff --git a/include/rabitqlib/simd/space_dispatch.hpp b/include/rabitqlib/simd/space_dispatch.hpp index 67d5e64..1403e1f 100644 --- a/include/rabitqlib/simd/space_dispatch.hpp +++ b/include/rabitqlib/simd/space_dispatch.hpp @@ -85,6 +85,7 @@ void new_transpose_bin_avx2( void new_transpose_bin_512_avx2( const uint8_t* q, uint64_t* tq, size_t padded_dim, size_t b_query ); +float mask_ip_x0_q_avx2(const float* query, const uint8_t* data, size_t padded_dim); float mask_ip_x0_q_avx2(const float* query, const uint64_t* data, size_t padded_dim); void scalar_quantize_uint8_avx2( uint8_t* result, const float* vec0, size_t dim, float lo, float delta @@ -99,6 +100,7 @@ void new_transpose_bin_avx512( void new_transpose_bin_512_avx512( const uint8_t* q, uint64_t* tq, size_t padded_dim, size_t b_query ); +float mask_ip_x0_q_avx512(const float* query, const uint8_t* data, size_t padded_dim); float mask_ip_x0_q_avx512(const float* query, const uint64_t* data, size_t padded_dim); void scalar_quantize_uint8_avx512( uint8_t* result, const float* vec0, size_t dim, float lo, float delta diff --git a/include/rabitqlib/simd/warmup_dispatch.hpp b/include/rabitqlib/simd/warmup_dispatch.hpp index f7899cb..bae9358 100644 --- a/include/rabitqlib/simd/warmup_dispatch.hpp +++ b/include/rabitqlib/simd/warmup_dispatch.hpp @@ -5,6 +5,15 @@ namespace rabitqlib::simd { +float warmup_ip_x0_q_512_avx2( + const uint8_t* data, + const uint64_t* query, + float delta, + float vl, + size_t padded_dim, + size_t b_query +); + float warmup_ip_x0_q_512_avx2( const uint64_t* data, const uint64_t* query, @@ -14,6 +23,15 @@ float warmup_ip_x0_q_512_avx2( size_t b_query ); +float warmup_ip_x0_q_512_avx512( + const uint8_t* data, + const uint64_t* query, + float delta, + float vl, + size_t padded_dim, + size_t b_query +); + float warmup_ip_x0_q_512_avx512( const uint64_t* data, const uint64_t* query, diff --git a/include/rabitqlib/utils/array.hpp b/include/rabitqlib/utils/array.hpp index ee23b4c..03ea19f 100644 --- a/include/rabitqlib/utils/array.hpp +++ b/include/rabitqlib/utils/array.hpp @@ -19,10 +19,11 @@ #pragma once -#include #include #include +#include #include +#include #include #include #include @@ -39,7 +40,12 @@ template static_assert(std::is_same_v); size_t res = 1; - std::for_each(dims.begin(), dims.end(), [&](auto cur_d) { res *= cur_d; }); + for (const size_t cur_d : dims) { + if (cur_d != 0 && res > std::numeric_limits::max() / cur_d) { + throw std::bad_array_new_length(); + } + res *= cur_d; + } return res; } } // namespace array_impl @@ -56,7 +62,13 @@ class Array { [[nodiscard]] constexpr auto size() const -> size_t { return array_impl::size(dims_); } /// @brief num of bytes for all data objects - [[nodiscard]] constexpr auto bytes() const -> size_t { return sizeof(T) * size(); } + [[nodiscard]] constexpr auto bytes() const -> size_t { + const size_t num_elements = size(); + if (num_elements > std::numeric_limits::max() / sizeof(T)) { + throw std::bad_array_new_length(); + } + return sizeof(T) * num_elements; + } void destroy() { size_t num_elements = size(); @@ -131,4 +143,4 @@ class Array { [[no_unique_address]] Dims dims_; [[no_unique_address]] Alloc allocator_; }; -} // namespace rabitqlib \ No newline at end of file +} // namespace rabitqlib diff --git a/include/rabitqlib/utils/buffer.hpp b/include/rabitqlib/utils/buffer.hpp index f06da97..2da7570 100644 --- a/include/rabitqlib/utils/buffer.hpp +++ b/include/rabitqlib/utils/buffer.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include "rabitqlib/defines.hpp" @@ -23,7 +24,14 @@ template class SearchBuffer { private: std::vector, memory::AlignedAllocator>> data_; - size_t size_ = 0, cur_ = 0, capacity_; + size_t size_ = 0, cur_ = 0, capacity_ = 0; + + [[nodiscard]] static size_t storage_size(size_t capacity) { + if (capacity == std::numeric_limits::max()) { + throw std::length_error("SearchBuffer capacity is too large"); + } + return capacity + 1; + } [[nodiscard]] auto binary_search(T dist) const { size_t lo = 0; @@ -47,7 +55,8 @@ class SearchBuffer { public: SearchBuffer() = default; - explicit SearchBuffer(size_t capacity) : data_(capacity + 1), capacity_(capacity) {} + explicit SearchBuffer(size_t capacity) + : data_(storage_size(capacity)), capacity_(capacity) {} // insert a data point into buffer void insert(PID data_id, T dist) { @@ -84,12 +93,15 @@ class SearchBuffer { [[nodiscard]] auto has_next() const -> bool { return cur_ < size_; } void resize(size_t new_size) { - this->capacity_ = new_size; data_ = std::vector, memory::AlignedAllocator>>( - capacity_ + 1 + storage_size(new_size) ); + capacity_ = new_size; + clear(); } + [[nodiscard]] size_t size() const { return size_; } + void copy_results(PID* knn) const { for (size_t i = 0; i < size_; ++i) { knn[i] = data_[i].id; diff --git a/include/rabitqlib/utils/cpu_features.hpp b/include/rabitqlib/utils/cpu_features.hpp index 57a6827..fafe7d1 100644 --- a/include/rabitqlib/utils/cpu_features.hpp +++ b/include/rabitqlib/utils/cpu_features.hpp @@ -1,5 +1,7 @@ #pragma once +#include + namespace rabitqlib::cpu { struct Features { @@ -16,4 +18,12 @@ bool has_avx2(); bool has_avx512_core(); bool has_avx512_popcnt(); +namespace detail { + +Features filter_usable_features( + const Features& hardware, bool avx, bool osxsave, uint64_t xcr0 +); + +} // namespace detail + } // namespace rabitqlib::cpu diff --git a/include/rabitqlib/utils/io.hpp b/include/rabitqlib/utils/io.hpp index bf70e91..3bf2ff4 100644 --- a/include/rabitqlib/utils/io.hpp +++ b/include/rabitqlib/utils/io.hpp @@ -1,19 +1,61 @@ #pragma once -#include #include #include #include #include #include +#include #include #include #include +#include namespace rabitqlib { +namespace io_impl { + +inline size_t checked_add(size_t lhs, size_t rhs) { + if (lhs > std::numeric_limits::max() - rhs) { + throw std::length_error("File layout exceeds size_t"); + } + return lhs + rhs; +} + +inline size_t checked_multiply(size_t lhs, size_t rhs) { + if (lhs != 0 && rhs > std::numeric_limits::max() / lhs) { + throw std::length_error("File layout exceeds size_t"); + } + return lhs * rhs; +} + +inline void read_exact( + std::ifstream& input, void* destination, size_t bytes, const char* description +) { + if (bytes > static_cast(std::numeric_limits::max())) { + throw std::length_error("File field is too large to read"); + } + input.read(reinterpret_cast(destination), static_cast(bytes)); + if (!input) { + throw std::runtime_error( + std::string("Unexpected end of file while reading ") + description + ); + } +} + +template +void read_value(std::ifstream& input, T& value, const char* description) { + read_exact(input, &value, sizeof(value), description); +} + +} // namespace io_impl + // get num of bytes inline size_t get_filesize(const char* filename) { - return std::filesystem::file_size(filename); + const auto file_size = std::filesystem::file_size(filename); + if (file_size > std::numeric_limits::max()) { + throw std::length_error("File is too large to address"); + } + return static_cast(file_size); } inline bool file_exists(const char* filename) { return std::filesystem::exists(filename); } @@ -25,26 +67,46 @@ void load_vecs(const char* filename, M& row_mat) { throw std::runtime_error("File does not exist: " + std::string(filename)); } - assert((std::is_same_v> == true)); + static_assert(std::is_same_v>); - uint32_t tmp; - size_t file_size = get_filesize(filename); + const size_t file_size = get_filesize(filename); + if (file_size < sizeof(uint32_t)) { + throw std::runtime_error("Vector file is too small to contain a dimension"); + } std::ifstream input(filename, std::ios::binary); + if (!input.is_open()) { + throw std::runtime_error("Cannot open vector file: " + std::string(filename)); + } - input.read(reinterpret_cast(&tmp), sizeof(uint32_t)); + uint32_t stored_cols = 0; + io_impl::read_value(input, stored_cols, "vector dimension"); + if (stored_cols == 0) { + throw std::runtime_error("Vector dimension must be positive"); + } - size_t cols = tmp; - size_t rows = file_size / (cols * sizeof(T) + sizeof(uint32_t)); - row_mat = M(rows, cols); + const size_t cols = stored_cols; + const size_t record_bytes = + io_impl::checked_add(sizeof(uint32_t), io_impl::checked_multiply(cols, sizeof(T))); + if (file_size % record_bytes != 0) { + throw std::runtime_error("Vector file size is not a whole number of records"); + } + const size_t rows = file_size / record_bytes; + M loaded(rows, cols); input.seekg(0, std::ifstream::beg); for (size_t i = 0; i < rows; i++) { - input.read(reinterpret_cast(&tmp), sizeof(uint32_t)); - input.read(reinterpret_cast(&row_mat(i, 0)), sizeof(T) * cols); + uint32_t row_cols = 0; + io_impl::read_value(input, row_cols, "row dimension"); + if (row_cols != stored_cols) { + throw std::runtime_error("Vector file contains inconsistent row dimensions"); + } + io_impl::read_exact( + input, &loaded(i, 0), io_impl::checked_multiply(sizeof(T), cols), "vector data" + ); } - input.close(); + row_mat = std::move(loaded); } // load .*bin file to a matrix (e.g., RowMajorFloatMat) @@ -54,21 +116,40 @@ void load_bin(const char* filename, M& row_mat) { throw std::runtime_error("File does not exist: " + std::string(filename)); } - assert((std::is_same_v> == true)); + static_assert(std::is_same_v>); - uint32_t rows; - uint32_t cols; + const size_t file_size = get_filesize(filename); + if (file_size < 2 * sizeof(uint32_t)) { + throw std::runtime_error("Binary matrix file is too small to contain its header"); + } std::ifstream input(filename, std::ios::binary); + if (!input.is_open()) { + throw std::runtime_error( + "Cannot open binary matrix file: " + std::string(filename) + ); + } - input.read(reinterpret_cast(&rows), sizeof(uint32_t)); - input.read(reinterpret_cast(&cols), sizeof(uint32_t)); - - row_mat = M(rows, cols); + uint32_t stored_rows = 0; + uint32_t stored_cols = 0; + io_impl::read_value(input, stored_rows, "matrix row count"); + io_impl::read_value(input, stored_cols, "matrix column count"); + if (stored_rows == 0 || stored_cols == 0) { + throw std::runtime_error("Binary matrix dimensions must be positive"); + } - for (size_t i = 0; i < rows; i++) { - input.read(reinterpret_cast(&row_mat(i, 0)), sizeof(T) * cols); + const size_t rows = stored_rows; + const size_t cols = stored_cols; + const size_t payload_bytes = + io_impl::checked_multiply(io_impl::checked_multiply(rows, cols), sizeof(T)); + const size_t expected_file_size = + io_impl::checked_add(2 * sizeof(uint32_t), payload_bytes); + if (file_size != expected_file_size) { + throw std::runtime_error("Binary matrix payload size does not match its header"); } - input.close(); + M loaded(rows, cols); + io_impl::read_exact(input, loaded.data(), payload_bytes, "matrix data"); + + row_mat = std::move(loaded); } } // namespace rabitqlib diff --git a/include/rabitqlib/utils/memory.hpp b/include/rabitqlib/utils/memory.hpp index 93cd490..af11ee6 100644 --- a/include/rabitqlib/utils/memory.hpp +++ b/include/rabitqlib/utils/memory.hpp @@ -11,8 +11,6 @@ #include #include -#include "rabitqlib/utils/tools.hpp" - namespace rabitqlib::memory { #define PORTABLE_ALIGN32 __attribute__((aligned(32))) #define PORTABLE_ALIGN64 __attribute__((aligned(64))) @@ -21,13 +19,30 @@ template class AlignedAllocator { private: static_assert(Alignment >= alignof(T)); + static_assert((Alignment & (Alignment - 1)) == 0, "Alignment must be a power of two"); + + template + using ReboundAllocator = AlignedAllocator; + + [[nodiscard]] static constexpr size_t aligned_size(size_t nbytes) { + const size_t remainder = nbytes % Alignment; + if (remainder == 0) { + return nbytes; + } + const size_t padding = Alignment - remainder; + if (nbytes > std::numeric_limits::max() - padding) { + throw std::bad_array_new_length(); + } + return nbytes + padding; + } public: using value_type = T; + using is_always_equal = std::true_type; template struct rebind { - using other = AlignedAllocator; + using other = ReboundAllocator; }; constexpr AlignedAllocator() noexcept = default; @@ -35,15 +50,32 @@ class AlignedAllocator { constexpr AlignedAllocator(const AlignedAllocator&) noexcept = default; template - constexpr explicit AlignedAllocator(AlignedAllocator const&) noexcept {} + constexpr explicit AlignedAllocator(const ReboundAllocator&) noexcept {} + + friend constexpr bool + operator==(const AlignedAllocator&, const AlignedAllocator&) noexcept { + return true; + } + + friend constexpr bool + operator!=(const AlignedAllocator&, const AlignedAllocator&) noexcept { + return false; + } [[nodiscard]] T* allocate(std::size_t n) { if (n > std::numeric_limits::max() / sizeof(T)) { throw std::bad_array_new_length(); } - auto nbytes = round_up_to_multiple_of(n * sizeof(T), Alignment); + if (n == 0) { + return nullptr; + } + + const auto nbytes = aligned_size(n * sizeof(T)); auto* ptr = std::aligned_alloc(Alignment, nbytes); + if (ptr == nullptr) { + throw std::bad_alloc(); + } if (HugePage) { madvise(ptr, nbytes, MADV_HUGEPAGE); } @@ -78,8 +110,23 @@ struct Allocator { template inline T* align_allocate(size_t nbytes) { - auto size = round_up_to_multiple_of(nbytes, Alignment); + static_assert(Alignment >= alignof(T)); + static_assert((Alignment & (Alignment - 1)) == 0, "Alignment must be a power of two"); + + if (nbytes == 0) { + return nullptr; + } + + const size_t remainder = nbytes % Alignment; + const size_t padding = remainder == 0 ? 0 : Alignment - remainder; + if (nbytes > std::numeric_limits::max() - padding) { + throw std::bad_array_new_length(); + } + const size_t size = nbytes + padding; void* ptr = std::aligned_alloc(Alignment, size); + if (ptr == nullptr) { + throw std::bad_alloc(); + } if (HugePage) { madvise(ptr, size, MADV_HUGEPAGE); } diff --git a/include/rabitqlib/utils/rotator.hpp b/include/rabitqlib/utils/rotator.hpp index f0d6b27..4c401a2 100644 --- a/include/rabitqlib/utils/rotator.hpp +++ b/include/rabitqlib/utils/rotator.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,9 @@ inline size_t padding_requirement(size_t dim, RotatorType type) { return dim; } if (type == RotatorType::FhtKacRotator) { + if (dim > std::numeric_limits::max() - 63) { + throw std::invalid_argument("Rotator dimension is too large to pad"); + } return round_up_to_multiple(dim, 64); } throw std::invalid_argument("Invalid rotator type in padding_requirement()"); @@ -273,10 +277,19 @@ template Rotator* choose_rotator( size_t dim, RotatorType type = RotatorType::FhtKacRotator, size_t padded_dim = 0 ) { + if (dim == 0) { + throw std::invalid_argument("Rotator dimension must be positive"); + } if (padded_dim == 0) { padded_dim = rotator_impl::padding_requirement(dim, type); } + if (padded_dim < dim) { + throw std::invalid_argument( + "Padded rotator dimension must not be smaller than input" + ); + } + if (padded_dim != rotator_impl::padding_requirement(padded_dim, type)) { throw std::invalid_argument("Invalid padded dimension for the rotator type"); } diff --git a/include/rabitqlib/utils/space.hpp b/include/rabitqlib/utils/space.hpp index 1891fec..9c8549b 100644 --- a/include/rabitqlib/utils/space.hpp +++ b/include/rabitqlib/utils/space.hpp @@ -144,24 +144,33 @@ inline T normalize_vec( return static_cast(dim) * value; } -// pack 0/1 data to usigned integer +// Pack 0/1 data into words without requiring the destination byte storage to +// contain aligned, lifetime-started T objects. template -inline void pack_binary( - const int* __restrict__ binary_code, T* __restrict__ compact_code, size_t length +inline void pack_binary_to_bytes( + const int* __restrict__ binary_code, uint8_t* __restrict__ compact_code, size_t length ) { constexpr size_t kTypeBits = sizeof(T) * 8; - auto* output = reinterpret_cast(compact_code); for (size_t i = 0; i < length; i += kTypeBits) { T cur = 0; for (size_t j = 0; j < kTypeBits; ++j) { cur |= (static_cast(binary_code[i + j]) << (kTypeBits - 1 - j)); } - std::memcpy(output, &cur, sizeof(cur)); - output += sizeof(cur); + std::memcpy(compact_code, &cur, sizeof(cur)); + compact_code += sizeof(cur); } } +// Backward-compatible typed-output overload. The implementation remains +// byte-oriented, so it does not dereference compact_code as T. +template +inline void pack_binary( + const int* __restrict__ binary_code, T* __restrict__ compact_code, size_t length +) { + pack_binary_to_bytes(binary_code, reinterpret_cast(compact_code), length); +} + template inline void data_range(const T* __restrict__ vec0, size_t dim, T& lo, T& hi) { ConstRowMajorArrayMap v0(vec0, 1, dim); @@ -324,6 +333,7 @@ void new_transpose_bin_512( const uint8_t* q, uint64_t* tq, size_t padded_dim, size_t b_query ); +float mask_ip_x0_q(const float* query, const uint8_t* data, size_t padded_dim); float mask_ip_x0_q(const float* query, const uint64_t* data, size_t padded_dim); inline float mask_ip_x0_q_old(const float* query, const uint64_t* data, size_t padded_dim) { diff --git a/include/rabitqlib/utils/warmup_space.hpp b/include/rabitqlib/utils/warmup_space.hpp index 2782e7b..6f65bea 100644 --- a/include/rabitqlib/utils/warmup_space.hpp +++ b/include/rabitqlib/utils/warmup_space.hpp @@ -5,6 +5,15 @@ namespace rabitqlib { +float warmup_ip_x0_q_512( + const uint8_t* data, + const uint64_t* query, + float delta, + float vl, + size_t padded_dim, + size_t b_query +); + float warmup_ip_x0_q_512( const uint64_t* data, const uint64_t* query, diff --git a/python_bindings/ivf_bindings.cpp b/python_bindings/ivf_bindings.cpp index 03b0517..9ab8f91 100644 --- a/python_bindings/ivf_bindings.cpp +++ b/python_bindings/ivf_bindings.cpp @@ -1,14 +1,24 @@ -#include +#include +#include +#include +#include +#include // IWYU pragma: keep; registers std::optional casters +#include #include +#include #include #include #include +#include #include #include #include "bindings_common.hpp" +#include "rabitqlib/defines.hpp" +#include "rabitqlib/index/ivf/initializer.hpp" #include "rabitqlib/index/ivf/ivf.hpp" +#include "rabitqlib/utils/rotator.hpp" namespace py = pybind11; diff --git a/python_bindings/symqg_bindings.cpp b/python_bindings/symqg_bindings.cpp index 68afbfa..9a54bf0 100644 --- a/python_bindings/symqg_bindings.cpp +++ b/python_bindings/symqg_bindings.cpp @@ -1,17 +1,27 @@ -#include +#include +#include +#include +#include +#include #include #include +#include +#include #include #include #include +#include #include #include #include #include "bindings_common.hpp" +#include "rabitqlib/defines.hpp" +#include "rabitqlib/fastscan/fastscan.hpp" #include "rabitqlib/index/symqg/qg.hpp" #include "rabitqlib/index/symqg/qg_builder.hpp" +#include "rabitqlib/utils/rotator.hpp" namespace py = pybind11; @@ -89,6 +99,9 @@ class SymqgIndex { if (ef == 0) { throw std::invalid_argument("ef must be positive"); } + if (ef < k) { + throw std::invalid_argument("ef must be at least k"); + } if (static_cast(query_array.shape(1)) != dim_) { throw std::invalid_argument("query dimension does not match index dim"); } @@ -102,8 +115,6 @@ class SymqgIndex { auto dists = py::array_t(shape); auto* ids_data = ids.mutable_data(); auto* dists_data = dists.mutable_data(); - std::fill(ids_data, ids_data + ids.size(), 0); - std::fill(dists_data, dists_data + dists.size(), 0.0F); const auto* queries_data = query_array.data(); const size_t requested_threads = diff --git a/scripts/check-tidy.sh b/scripts/check-tidy.sh index 15b7c85..cc7125d 100755 --- a/scripts/check-tidy.sh +++ b/scripts/check-tidy.sh @@ -50,12 +50,14 @@ if [[ -n "${CLANG_RESOURCE_DIR:-}" ]]; then extra_args+=("-extra-arg-before=-resource-dir=$CLANG_RESOURCE_DIR") fi for include_dir in "${system_include_dirs[@]}"; do + # Append compiler defaults so dependency paths from the compilation database + # take precedence over system installations (for example, pybind11). if [[ "$include_dir" == */lib/gcc/*/include ]]; then # Keep Clang's intrinsic headers ahead of GCC's, while still making # compiler-provided headers such as omp.h available. - extra_args+=("-extra-arg-before=-idirafter$include_dir") + extra_args+=("-extra-arg=-idirafter$include_dir") else - extra_args+=("-extra-arg-before=-isystem$include_dir") + extra_args+=("-extra-arg=-isystem$include_dir") fi done diff --git a/src/simd/dispatch.cpp b/src/simd/dispatch.cpp index 5abcef1..10f9e14 100644 --- a/src/simd/dispatch.cpp +++ b/src/simd/dispatch.cpp @@ -130,7 +130,7 @@ static void missing_new_transpose_bin_512(const uint8_t*, uint64_t*, size_t, siz missing_feature("new_transpose_bin_512"); } -static float missing_mask_ip_x0_q(const float*, const uint64_t*, size_t) { +static float missing_mask_ip_x0_q(const float*, const uint8_t*, size_t) { missing_feature("mask ip x0 q"); } @@ -149,7 +149,7 @@ static void missing_fastscan_accumulate_hacc( } static float missing_warmup_ip_x0_q_512( - const uint64_t*, const uint64_t*, float, float, size_t, size_t + const uint8_t*, const uint64_t*, float, float, size_t, size_t ) { missing_feature("warmup_ip_x0_q_512"); } @@ -341,12 +341,12 @@ const NewTransposeBin512Fn kNewTransposeBin512Fn = [] { } }(); -using MaskIpX0QFn = float (*)(const float*, const uint64_t*, size_t); +using MaskIpX0QFn = float (*)(const float*, const uint8_t*, size_t); const MaskIpX0QFn kMaskIpX0QFn = [] { if (cpu::has_avx512_core()) { - return simd::mask_ip_x0_q_avx512; + return static_cast(simd::mask_ip_x0_q_avx512); } else if (cpu::has_avx2()) { - return simd::mask_ip_x0_q_avx2; + return static_cast(simd::mask_ip_x0_q_avx2); } else { return simd::missing_mask_ip_x0_q; } @@ -412,10 +412,14 @@ void new_transpose_bin_512( kNewTransposeBin512Fn(q, tq, padded_dim, b_query); } -float mask_ip_x0_q(const float* query, const uint64_t* data, size_t padded_dim) { +float mask_ip_x0_q(const float* query, const uint8_t* data, size_t padded_dim) { return kMaskIpX0QFn(query, data, padded_dim); } +float mask_ip_x0_q(const float* query, const uint64_t* data, size_t padded_dim) { + return mask_ip_x0_q(query, reinterpret_cast(data), padded_dim); +} + } // namespace rabitqlib namespace rabitqlib::fastscan { @@ -480,10 +484,18 @@ void accumulate( uint16_t* __restrict__ result, size_t dim ) { + if (dim == 0 || dim % 16 != 0) { + throw std::invalid_argument("FastScan dimension must be a positive multiple of 16"); + } kAccumulateFn(codes, lp_table, result, dim); } void transfer_lut_hacc(const uint16_t* lut, size_t dim, uint8_t* hc_lut) { + if (dim == 0 || dim % 16 != 0) { + throw std::invalid_argument( + "high-accuracy FastScan dimension must be a positive multiple of 16" + ); + } kTransferLutHaccFn(lut, dim, hc_lut); } @@ -493,6 +505,11 @@ void accumulate_hacc( int32_t* accu_res, size_t dim ) { + if (dim == 0 || dim % 16 != 0) { + throw std::invalid_argument( + "high-accuracy FastScan dimension must be a positive multiple of 16" + ); + } kAccumulateHaccFn(codes, hc_lut, accu_res, dim); } @@ -501,19 +518,19 @@ void accumulate_hacc( namespace rabitqlib { using WarmupIpX0Q512Fn = - float (*)(const uint64_t*, const uint64_t*, float, float, size_t, size_t); + float (*)(const uint8_t*, const uint64_t*, float, float, size_t, size_t); const WarmupIpX0Q512Fn kWarmupIpX0Q512Fn = [] { if (rabitqlib::cpu::has_avx512_popcnt()) { - return rabitqlib::simd::warmup_ip_x0_q_512_avx512; + return static_cast(rabitqlib::simd::warmup_ip_x0_q_512_avx512); } else if (rabitqlib::cpu::has_avx2()) { - return rabitqlib::simd::warmup_ip_x0_q_512_avx2; + return static_cast(rabitqlib::simd::warmup_ip_x0_q_512_avx2); } else { return rabitqlib::simd::missing_warmup_ip_x0_q_512; } }(); float warmup_ip_x0_q_512( - const uint64_t* data, + const uint8_t* data, const uint64_t* query, float delta, float vl, @@ -523,4 +540,17 @@ float warmup_ip_x0_q_512( return kWarmupIpX0Q512Fn(data, query, delta, vl, padded_dim, b_query); } +float warmup_ip_x0_q_512( + const uint64_t* data, + const uint64_t* query, + float delta, + float vl, + size_t padded_dim, + size_t b_query +) { + return warmup_ip_x0_q_512( + reinterpret_cast(data), query, delta, vl, padded_dim, b_query + ); +} + } // namespace rabitqlib diff --git a/src/simd/fastscan_avx512.cpp b/src/simd/fastscan_avx512.cpp index bf01939..e019b78 100644 --- a/src/simd/fastscan_avx512.cpp +++ b/src/simd/fastscan_avx512.cpp @@ -110,8 +110,8 @@ void transfer_lut_hacc_avx512(const uint16_t* lut, size_t dim, uint8_t* hc_lut) ); __m128i lo = _mm512_cvtepi32_epi8(tmp); __m128i hi = _mm512_cvtepi32_epi8(_mm512_srli_epi32(tmp, 8)); - _mm_store_si128(reinterpret_cast<__m128i*>(fill_lo), lo); - _mm_store_si128(reinterpret_cast<__m128i*>(fill_hi), hi); + _mm_storeu_si128(reinterpret_cast<__m128i*>(fill_lo), lo); + _mm_storeu_si128(reinterpret_cast<__m128i*>(fill_hi), hi); lut += 16; } } diff --git a/src/simd/space_avx2.cpp b/src/simd/space_avx2.cpp index 45595b9..2a30a5b 100644 --- a/src/simd/space_avx2.cpp +++ b/src/simd/space_avx2.cpp @@ -171,9 +171,9 @@ void new_transpose_bin_512_avx2( } } -float mask_ip_x0_q_avx2(const float* query, const uint64_t* data, size_t padded_dim) { +float mask_ip_x0_q_avx2(const float* query, const uint8_t* data, size_t padded_dim) { const size_t num_blk = padded_dim / 64; - const auto* it_data = reinterpret_cast(data); + const auto* it_data = data; const float* it_query = query; const __m256i shifts0 = _mm256_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7); const __m256i shifts1 = _mm256_setr_epi32(8, 9, 10, 11, 12, 13, 14, 15); @@ -214,4 +214,8 @@ float mask_ip_x0_q_avx2(const float* query, const uint64_t* data, size_t padded_ return _mm_cvtss_f32(_mm_add_ss(lanes, _mm_movehdup_ps(lanes))); } +float mask_ip_x0_q_avx2(const float* query, const uint64_t* data, size_t padded_dim) { + return mask_ip_x0_q_avx2(query, reinterpret_cast(data), padded_dim); +} + } // namespace rabitqlib::simd diff --git a/src/simd/space_avx512.cpp b/src/simd/space_avx512.cpp index abdb78e..e466fde 100644 --- a/src/simd/space_avx512.cpp +++ b/src/simd/space_avx512.cpp @@ -127,9 +127,9 @@ void new_transpose_bin_512_avx512( } } -float mask_ip_x0_q_avx512(const float* query, const uint64_t* data, size_t padded_dim) { +float mask_ip_x0_q_avx512(const float* query, const uint8_t* data, size_t padded_dim) { const size_t num_blk = padded_dim / 64; - const uint8_t* it_data = reinterpret_cast(data); + const uint8_t* it_data = data; const float* it_query = query; // __m512 sum0 = _mm512_setzero_ps(); @@ -166,4 +166,8 @@ float mask_ip_x0_q_avx512(const float* query, const uint64_t* data, size_t padde return _mm512_reduce_add_ps(sum); } +float mask_ip_x0_q_avx512(const float* query, const uint64_t* data, size_t padded_dim) { + return mask_ip_x0_q_avx512(query, reinterpret_cast(data), padded_dim); +} + } // namespace rabitqlib::simd diff --git a/src/simd/warmup_avx2.cpp b/src/simd/warmup_avx2.cpp index b9d5fd8..e187744 100644 --- a/src/simd/warmup_avx2.cpp +++ b/src/simd/warmup_avx2.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "rabitqlib/simd/warmup_dispatch.hpp" @@ -62,7 +63,7 @@ static inline __m256i popcount_avx2(__m256i v) { } float warmup_ip_x0_q_512_avx2( - const uint64_t* data, + const uint8_t* data, const uint64_t* query, float delta, float vl, @@ -88,8 +89,8 @@ float warmup_ip_x0_q_512_avx2( // Load 64 bytes of data using paired 32-byte loads __m256i data_vec_lo = _mm256_loadu_si256(reinterpret_cast(data)); __m256i data_vec_hi = - _mm256_loadu_si256(reinterpret_cast(data + 4)); - data += 8; // Advance 8 x 64-bit ints (64 bytes) + _mm256_loadu_si256(reinterpret_cast(data + 32)); + data += 64; acc_ppc = _mm256_add_epi64(acc_ppc, popcount_avx2(data_vec_lo)); acc_ppc = _mm256_add_epi64(acc_ppc, popcount_avx2(data_vec_hi)); @@ -114,37 +115,25 @@ float warmup_ip_x0_q_512_avx2( size_t remaining_dim = padded_dim - i; if (remaining_dim > 0) { size_t num_chunks_64 = remaining_dim / 64; - size_t num_chunks_32 = remaining_dim / 32; - - size_t chunks_lo = (num_chunks_32 > 8) ? 8 : num_chunks_32; - size_t chunks_hi = (num_chunks_32 > 8) ? (num_chunks_32 - 8) : 0; - - // 1. Create a baseline sequence register - __m256i sequence = _mm256_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7); - - // 2. Generate masks in-register using Greater-Than comparisons - // If chunks_lo is 3, limit will be [3,3,3,3,3,3,3,3]. - // 3 > seq results in [-1, -1, -1, 0, 0, 0, 0, 0], which is the exact mask needed. - __m256i limit_lo = _mm256_set1_epi32(static_cast(chunks_lo)); - __m256i mask_lo = _mm256_cmpgt_epi32(limit_lo, sequence); + size_t remaining_bytes = num_chunks_64 * sizeof(uint64_t); - __m256i limit_hi = _mm256_set1_epi32(static_cast(chunks_hi)); - __m256i mask_hi = _mm256_cmpgt_epi32(limit_hi, sequence); - - // 3. Vectorized execution continues with zero memory latency + alignas(32) uint8_t data_tail[64]{}; + std::memcpy(data_tail, data, remaining_bytes); __m256i data_vec_lo = - _mm256_maskload_epi32(reinterpret_cast(data), mask_lo); + _mm256_load_si256(reinterpret_cast(data_tail)); __m256i data_vec_hi = - _mm256_maskload_epi32(reinterpret_cast(data + 4), mask_hi); + _mm256_load_si256(reinterpret_cast(data_tail + 32)); acc_ppc = _mm256_add_epi64(acc_ppc, popcount_avx2(data_vec_lo)); acc_ppc = _mm256_add_epi64(acc_ppc, popcount_avx2(data_vec_hi)); for (size_t j = 0; j < b_query; ++j) { + alignas(32) uint8_t query_tail[64]{}; + std::memcpy(query_tail, query, remaining_bytes); __m256i query_vec_lo = - _mm256_maskload_epi32(reinterpret_cast(query), mask_lo); + _mm256_load_si256(reinterpret_cast(query_tail)); __m256i query_vec_hi = - _mm256_maskload_epi32(reinterpret_cast(query + 4), mask_hi); + _mm256_load_si256(reinterpret_cast(query_tail + 32)); query += num_chunks_64; __m256i pop_lo = popcount_avx2(_mm256_and_si256(data_vec_lo, query_vec_lo)); @@ -174,4 +163,17 @@ float warmup_ip_x0_q_512_avx2( return (delta * static_cast(ip_scalar)) + (vl * static_cast(ppc_scalar)); } +float warmup_ip_x0_q_512_avx2( + const uint64_t* data, + const uint64_t* query, + float delta, + float vl, + size_t padded_dim, + size_t b_query +) { + return warmup_ip_x0_q_512_avx2( + reinterpret_cast(data), query, delta, vl, padded_dim, b_query + ); +} + } // namespace rabitqlib::simd diff --git a/src/simd/warmup_avx512.cpp b/src/simd/warmup_avx512.cpp index 4333def..980cda5 100644 --- a/src/simd/warmup_avx512.cpp +++ b/src/simd/warmup_avx512.cpp @@ -8,7 +8,7 @@ namespace rabitqlib::simd { float warmup_ip_x0_q_512_avx512( - const uint64_t* data, + const uint8_t* data, const uint64_t* query, float delta, float vl, @@ -31,7 +31,7 @@ float warmup_ip_x0_q_512_avx512( for (; i < dim_end_512; i += 512) { __m512i data_vec = _mm512_loadu_si512(data); - data += 8; + data += 64; acc_ppc = _mm512_add_epi64(acc_ppc, _mm512_popcnt_epi64(data_vec)); @@ -72,4 +72,17 @@ float warmup_ip_x0_q_512_avx512( return (delta * static_cast(ip_scalar)) + (vl * static_cast(ppc_scalar)); } +float warmup_ip_x0_q_512_avx512( + const uint64_t* data, + const uint64_t* query, + float delta, + float vl, + size_t padded_dim, + size_t b_query +) { + return warmup_ip_x0_q_512_avx512( + reinterpret_cast(data), query, delta, vl, padded_dim, b_query + ); +} + } // namespace rabitqlib::simd diff --git a/src/utils/cpu_features.cpp b/src/utils/cpu_features.cpp index b4cf53a..920d10a 100644 --- a/src/utils/cpu_features.cpp +++ b/src/utils/cpu_features.cpp @@ -13,6 +13,12 @@ namespace rabitqlib::cpu { namespace { +#if defined(_M_X64) || defined(_M_IX86) || defined(__x86_64__) || defined(__i386__) +constexpr bool kIsX86 = true; +#else +constexpr bool kIsX86 = false; +#endif + #if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) void cpuid( uint32_t leaf, uint32_t subleaf, uint32_t* a, uint32_t* b, uint32_t* c, uint32_t* d @@ -34,32 +40,90 @@ void cpuid( void cpuid(uint32_t, uint32_t, uint32_t*, uint32_t*, uint32_t*, uint32_t*) {} #endif -Features detect_features() { - Features detected{}; +#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) +uint64_t xgetbv(uint32_t index) { return _xgetbv(index); } +#elif defined(__x86_64__) || defined(__i386__) +uint64_t xgetbv(uint32_t index) { + uint32_t eax; + uint32_t edx; + __asm__ volatile("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index)); + return (static_cast(edx) << 32) | eax; +} +#else +uint64_t xgetbv(uint32_t) { return 0; } +#endif -#if defined(__x86_64__) || defined(__i386__) - // leaf 1: ECX[28]=AVX, ECX[12]=FMA, ECX[23]=POPCNT - uint32_t eax, ebx, ecx, edx; +Features detect_features() { + Features hardware{}; + if constexpr (!kIsX86) { + return hardware; + } + + uint32_t eax = 0; + uint32_t ebx = 0; + uint32_t ecx = 0; + uint32_t edx = 0; + cpuid(0, 0, &eax, &ebx, &ecx, &edx); + const uint32_t max_leaf = eax; + if (max_leaf < 1) { + return hardware; + } + + // leaf 1: ECX[12]=FMA, ECX[27]=OSXSAVE, ECX[28]=AVX. cpuid(1, 0, &eax, &ebx, &ecx, &edx); + const bool fma = ((ecx >> 12) & 1U) != 0; + const bool osxsave = ((ecx >> 27) & 1U) != 0; + const bool avx = ((ecx >> 28) & 1U) != 0; + hardware.fma = fma; + + if (max_leaf >= 7) { + // leaf 7 (subleaf 0): EBX[5]=AVX2, EBX[16]=AVX512F, + // EBX[17]=AVX512DQ, EBX[30]=AVX512BW, + // ECX[14]=AVX512_VPOPCNTDQ. + uint32_t l7_eax = 0; + uint32_t l7_ebx = 0; + uint32_t l7_ecx = 0; + uint32_t l7_edx = 0; + cpuid(7, 0, &l7_eax, &l7_ebx, &l7_ecx, &l7_edx); + + hardware.avx2 = ((l7_ebx >> 5) & 1U) != 0; + hardware.avx512f = ((l7_ebx >> 16) & 1U) != 0; + hardware.avx512dq = ((l7_ebx >> 17) & 1U) != 0; + hardware.avx512bw = ((l7_ebx >> 30) & 1U) != 0; + hardware.avx512vpopcntdq = ((l7_ecx >> 14) & 1U) != 0; + } + + const uint64_t xcr0 = avx && osxsave ? xgetbv(0) : 0; + return detail::filter_usable_features(hardware, avx, osxsave, xcr0); +} - // leaf 7 (subleaf 0): EBX[5]=AVX2, EBX[16]=AVX512F, - // EBX[17]=AVX512DQ, EBX[30]=AVX512BW, - // ECX[14]=AVX512_VPOPCNTDQ - uint32_t l7_eax, l7_ebx, l7_ecx, l7_edx; - cpuid(7, 0, &l7_eax, &l7_ebx, &l7_ecx, &l7_edx); - - detected.fma = (ecx >> 12) & 1; - detected.avx2 = (l7_ebx >> 5) & 1; - detected.avx512f = (l7_ebx >> 16) & 1; - detected.avx512dq = (l7_ebx >> 17) & 1; - detected.avx512bw = (l7_ebx >> 30) & 1; - detected.avx512vpopcntdq = (l7_ecx >> 14) & 1; -#endif +} // namespace - return detected; +namespace detail { + +Features filter_usable_features( + const Features& hardware, bool avx, bool osxsave, uint64_t xcr0 +) { + constexpr uint64_t kAvxStateMask = (uint64_t{1} << 1) | (uint64_t{1} << 2); + constexpr uint64_t kAvx512StateMask = + kAvxStateMask | (uint64_t{1} << 5) | (uint64_t{1} << 6) | (uint64_t{1} << 7); + + const bool avx_state_enabled = + avx && osxsave && (xcr0 & kAvxStateMask) == kAvxStateMask; + const bool avx512_state_enabled = + avx_state_enabled && (xcr0 & kAvx512StateMask) == kAvx512StateMask; + + Features usable{}; + usable.fma = hardware.fma && avx_state_enabled; + usable.avx2 = hardware.avx2 && avx_state_enabled; + usable.avx512f = hardware.avx512f && avx512_state_enabled; + usable.avx512bw = hardware.avx512bw && avx512_state_enabled; + usable.avx512dq = hardware.avx512dq && avx512_state_enabled; + usable.avx512vpopcntdq = hardware.avx512vpopcntdq && avx512_state_enabled; + return usable; } -} // namespace +} // namespace detail const Features& features() { static const Features detected = detect_features(); @@ -73,7 +137,7 @@ bool has_avx2() { bool has_avx512_core() { const Features& detected = features(); - return detected.avx512f && detected.avx512bw && detected.avx512dq; + return detected.fma && detected.avx512f && detected.avx512bw && detected.avx512dq; } bool has_avx512_popcnt() { return has_avx512_core() && features().avx512vpopcntdq; } diff --git a/tests/python/test_ivf.py b/tests/python/test_ivf.py index 0922d74..e541935 100644 --- a/tests/python/test_ivf.py +++ b/tests/python/test_ivf.py @@ -115,6 +115,23 @@ def test_recall_vs_brute_force(built_ivf, base_data, query_data): assert r >= 0.5, f"Recall {r:.3f} too low" +def test_inner_product_routing_uses_inner_product(): + data = np.zeros((2, DIM), dtype=np.float32) + data[0, 0] = 0.9 + data[1, 0] = 100.0 + centroids = data.copy() + cluster_ids = np.array([0, 1], dtype=np.uint32) + query = np.zeros((1, DIM), dtype=np.float32) + query[0, 0] = 1.0 + + idx = IvfIndex(DIM, 2, 2, nbits=32, metric="ip") + idx.build(data, centroids, cluster_ids, num_threads=1) + ids, distances = idx.search(query, k=1, nprobe=1, num_threads=1) + + assert ids[0, 0] == 1 + np.testing.assert_allclose(distances[0, 0], -99.0, rtol=0, atol=1e-5) + + # ── optional parameters ─────────────────────────────────────────────────────── diff --git a/tests/python/test_symqg.py b/tests/python/test_symqg.py index 20ef6a5..d406202 100644 --- a/tests/python/test_symqg.py +++ b/tests/python/test_symqg.py @@ -1,5 +1,6 @@ """Tests for SymqgIndex: construction, search, properties, error handling, save/load.""" +import os import struct import numpy as np @@ -111,6 +112,11 @@ def test_search_before_build_raises(): idx.search(queries, k=1, ef=_EF) +def test_search_rejects_ef_smaller_than_k(built_symqg, query_data): + with pytest.raises(ValueError, match="ef must be at least k"): + built_symqg.search(query_data, k=10, ef=9) + + def test_invalid_degree_raises(): with pytest.raises(Exception): SymqgIndex(DIM, max_degree=16) @@ -121,6 +127,13 @@ def test_invalid_quantization_bits_raises(): SymqgIndex(DIM, max_degree=_MAX_DEGREE, quantization_bits=6) +def test_save_propagates_write_failure(built_symqg): + if not os.path.exists("/dev/full"): + pytest.skip("requires a failing output device") + with pytest.raises(RuntimeError): + built_symqg.save("/dev/full") + + @pytest.mark.parametrize("bits", [4, 8]) def test_qg_quant_build_search_and_roundtrip(bits, base_data, query_data, tmp_path): idx = SymqgIndex(DIM, max_degree=_MAX_DEGREE, quantization_bits=bits) diff --git a/tests/unit/rabitqlib/fastscan/fastscan_test.cpp b/tests/unit/rabitqlib/fastscan/fastscan_test.cpp index e176276..3ba14d6 100644 --- a/tests/unit/rabitqlib/fastscan/fastscan_test.cpp +++ b/tests/unit/rabitqlib/fastscan/fastscan_test.cpp @@ -2,12 +2,21 @@ #include +#include #include +#include #include #include #include +#include #include +#include "rabitqlib/defines.hpp" +#include "rabitqlib/fastscan/highacc_fastscan.hpp" +#include "rabitqlib/index/estimator.hpp" +#include "rabitqlib/index/lut.hpp" +#include "rabitqlib/index/query.hpp" +#include "rabitqlib/quantization/data_layout.hpp" #include "rabitqlib/simd/fastscan_dispatch.hpp" #include "rabitqlib/utils/cpu_features.hpp" @@ -166,5 +175,106 @@ TEST(FastScanPackingTest, AccumulatesReferenceLutValuesOnEverySupportedBackend) } } +TEST(FastScanHighAccuracyTest, RejectsDimensionsThatCannotFillASimdBlock) { + std::array lut{}; + std::array packed_lut{}; + std::array codes{}; + std::array low_result{}; + std::array result{}; + + for (size_t dim : {0U, 4U, 8U, 12U, 20U}) { + EXPECT_THROW( + accumulate(codes.data(), packed_lut.data(), low_result.data(), dim), + std::invalid_argument + ); + EXPECT_THROW( + transfer_lut_hacc(lut.data(), dim, packed_lut.data()), std::invalid_argument + ); + EXPECT_THROW( + accumulate_hacc(codes.data(), packed_lut.data(), result.data(), dim), + std::invalid_argument + ); + std::vector query(dim); + EXPECT_THROW((Lut(query.data(), dim, true)), std::invalid_argument); + EXPECT_THROW((Lut(query.data(), dim, false)), std::invalid_argument); + } +} + +TEST(FastScanHighAccuracyTest, Avx512TransferAcceptsUnalignedOutput) { + if (!cpu::has_avx512_core()) { + GTEST_SKIP() << "AVX512 is not supported on this CPU"; + } + + constexpr size_t kDim = 64; + std::array lut{}; + for (size_t i = 0; i < lut.size(); ++i) { + lut[i] = static_cast((i * 977U) & 0xffffU); + } + + std::array expected{}; + constexpr size_t kCodebooksPerRegister = 4; + constexpr size_t kBytesPerRegisterPair = 128; + constexpr size_t kBytesPerCodebook = 16; + constexpr size_t kHighByteOffset = 64; + for (size_t codebook = 0; codebook < kDim / 4; ++codebook) { + const size_t low_offset = + (codebook / kCodebooksPerRegister * kBytesPerRegisterPair) + + (codebook % kCodebooksPerRegister * kBytesPerCodebook); + for (size_t entry = 0; entry < 16; ++entry) { + const uint16_t value = lut[codebook * 16 + entry]; + expected[low_offset + entry] = static_cast(value); + expected[low_offset + kHighByteOffset + entry] = + static_cast(value >> 8); + } + } + + alignas(16) std::array storage{}; + ASSERT_NE(reinterpret_cast(storage.data() + 1) % 16, uintptr_t{0}); + simd::transfer_lut_hacc_avx512(lut.data(), kDim, storage.data() + 1); + EXPECT_TRUE(std::equal(expected.begin(), expected.end(), storage.begin() + 1)); +} + +TEST(FastScanHighAccuracyTest, AccumulatesAcrossChunks) { + if (!cpu::has_avx2()) { + GTEST_SKIP() << "AVX2 is not supported on this CPU"; + } + + constexpr size_t kDim = 4096; + std::vector query(kDim, 1.0F); + SplitBatchQuery q_obj(query.data(), kDim, 3, METRIC_L2, true); + + std::vector batch_data(BatchDataMap::data_bytes(kDim)); + BatchDataMap batch(batch_data.data(), kDim); + std::fill_n(batch.bin_code(), kDim * fastscan::kBatchSize / 8, uint8_t{0xff}); + std::fill_n(batch.f_add(), fastscan::kBatchSize, 0.0F); + std::fill_n(batch.f_rescale(), fastscan::kBatchSize, 1.0F); + std::fill_n(batch.f_error(), fastscan::kBatchSize, 0.0F); + + const int32_t scalar_accumulator = int32_t{65535} * static_cast(kDim / 4); + const float expected_ip = + q_obj.delta() * static_cast(scalar_accumulator) + q_obj.sum_vl_lut(); + const float expected_distance = expected_ip + q_obj.k1xsumq(); + + std::array estimated{}; + std::array lower{}; + std::array inner_products{}; + split_batch_estdist( + batch_data.data(), + q_obj, + kDim, + estimated.data(), + lower.data(), + inner_products.data(), + true + ); + + for (size_t lane = 0; lane < fastscan::kBatchSize; ++lane) { + EXPECT_TRUE(std::isfinite(estimated[lane])); + EXPECT_FLOAT_EQ(inner_products[lane], expected_ip); + EXPECT_FLOAT_EQ(estimated[lane], expected_distance); + EXPECT_FLOAT_EQ(lower[lane], expected_distance); + } +} + } // namespace } // namespace rabitqlib::fastscan diff --git a/tests/unit/rabitqlib/index/initializer_test.cpp b/tests/unit/rabitqlib/index/initializer_test.cpp new file mode 100644 index 0000000..8ce0b34 --- /dev/null +++ b/tests/unit/rabitqlib/index/initializer_test.cpp @@ -0,0 +1,45 @@ +#include "rabitqlib/index/ivf/initializer.hpp" + +#include + +#include +#include +#include + +namespace rabitqlib::ivf { +namespace { + +TEST(ParallelForTest, AutomaticThreadCountProcessesEveryItem) { + std::atomic calls{0}; + parallel_for(0, 100, 0, [&](size_t, size_t) { ++calls; }); + EXPECT_EQ(calls, 100U); +} + +TEST(ParallelForTest, EmptyRangeDoesNotInvokeFunction) { + size_t calls = 0; + parallel_for(5, 5, 0, [&](size_t, size_t) { ++calls; }); + EXPECT_EQ(calls, 0U); +} + +TEST(ParallelForTest, JoinsWorkersBeforeRethrowingFunctionException) { + std::atomic active{0}; + EXPECT_THROW( + parallel_for( + 0, + 100, + 4, + [&](size_t id, size_t) { + ++active; + --active; + if (id == 0) { + throw std::runtime_error("parallel failure"); + } + } + ), + std::runtime_error + ); + EXPECT_EQ(active, 0U); +} + +} // namespace +} // namespace rabitqlib::ivf diff --git a/tests/unit/rabitqlib/index/ivf_test.cpp b/tests/unit/rabitqlib/index/ivf_test.cpp index 6cf3ffd..d98dc63 100644 --- a/tests/unit/rabitqlib/index/ivf_test.cpp +++ b/tests/unit/rabitqlib/index/ivf_test.cpp @@ -2,9 +2,22 @@ #include +#include +#include +#include +#include #include +#include +#include +#include +#include #include #include +#include + +#include "rabitqlib/defines.hpp" +#include "rabitqlib/utils/buffer.hpp" +#include "rabitqlib/utils/rotator.hpp" namespace rabitqlib::ivf { namespace { @@ -16,6 +29,40 @@ TEST(IvfConfigurationTest, RejectsUnsupportedMetric) { ); } +TEST(IvfConfigurationTest, RejectsUnsupportedCountsAndNullConstructionInputs) { + constexpr size_t kDim = 64; + EXPECT_THROW((IVF(0, kDim, 1, 1)), std::invalid_argument); + EXPECT_THROW( + (IVF(buffer::kSearchBufferMaxPointCount + 1, kDim, 1, 1)), std::invalid_argument + ); + EXPECT_THROW((IVF(1, kDim, 0, 1)), std::invalid_argument); + EXPECT_THROW( + (IVF(1, kDim, buffer::kSearchBufferMaxPointCount + 1, 1)), std::invalid_argument + ); + + IVF index(1, kDim, 1, 1); + std::array vector{}; + const PID cluster = 0; + EXPECT_THROW( + index.construct(nullptr, vector.data(), &cluster, false, 1), std::invalid_argument + ); + EXPECT_THROW( + index.construct(vector.data(), nullptr, &cluster, false, 1), std::invalid_argument + ); + EXPECT_THROW( + index.construct(vector.data(), vector.data(), nullptr, false, 1), + std::invalid_argument + ); + + IVF unconfigured; + EXPECT_THROW( + unconfigured.construct(vector.data(), vector.data(), &cluster, false, 1), + std::logic_error + ); + const std::string path = ::testing::TempDir() + "rabitq_unconfigured_ivf.index"; + EXPECT_THROW(unconfigured.save(path.c_str()), std::logic_error); +} + TEST(IvfSearchTest, RawRerankingUsesOriginalCoordinates) { constexpr size_t kNum = 33; constexpr size_t kDim = 65; @@ -88,6 +135,108 @@ TEST(IvfSearchTest, AutomaticHighAccuracyMatchesBitPolicy) { } } +TEST(IvfSearchTest, RejectsUnbuiltStateAndInvalidArguments) { + constexpr size_t kDim = 64; + std::array query{}; + PID result = 0; + + IVF empty; + EXPECT_THROW(empty.search(query.data(), 1, 1, &result), std::logic_error); + + IVF index(1, kDim, 1, 1); + EXPECT_THROW(index.search(query.data(), 1, 1, &result), std::logic_error); + + std::array data; + data.fill(1.0F); + std::array centroid{}; + const PID cluster = 0; + index.construct(data.data(), centroid.data(), &cluster, false, 1); + + EXPECT_THROW(index.search(query.data(), 0, 1, &result), std::invalid_argument); + EXPECT_THROW(index.search(query.data(), 2, 1, &result), std::invalid_argument); + EXPECT_THROW( + index.search(query.data(), std::numeric_limits::max(), 1, &result), + std::invalid_argument + ); + EXPECT_THROW(index.search(query.data(), 1, 0, &result), std::invalid_argument); + EXPECT_THROW(index.search(nullptr, 1, 1, &result), std::invalid_argument); + EXPECT_THROW(index.search(query.data(), 1, 1, nullptr), std::invalid_argument); +} + +TEST(IvfSearchTest, FillsSentinelsWhenProbedClustersCannotFillK) { + constexpr size_t kNum = 2; + constexpr size_t kDim = 64; + std::array data{}; + std::array centroids{}; + std::array query{}; + std::array clusters{1, 1}; + std::fill(data.begin(), data.end(), 1.0F); + std::fill(centroids.begin() + static_cast(kDim), centroids.end(), 1.0F); + + IVF index(kNum, kDim, kNum, 32, MetricType::METRIC_L2, RotatorType::MatrixRotator); + index.construct(data.data(), centroids.data(), clusters.data(), false, 1); + + PID result = kPidMax; + float distance = -123.0F; + index.search(query.data(), 1, 1, &result, &distance); + EXPECT_EQ(result, kPidMax); + EXPECT_EQ(distance, std::numeric_limits::infinity()); +} + +TEST(IvfSearchTest, RoutesInnerProductQueriesByInnerProduct) { + constexpr size_t kNum = 2; + constexpr size_t kDim = 64; + std::vector data(kNum * kDim, 0.0F); + std::vector centroids(kNum * kDim, 0.0F); + std::array clusters{0, 1}; + std::array query{}; + data[0] = centroids[0] = 0.9F; + data[kDim] = centroids[kDim] = 100.0F; + query[0] = 1.0F; + + IVF index(kNum, kDim, kNum, 32, METRIC_IP); + index.construct(data.data(), centroids.data(), clusters.data(), false, 1); + + PID result = kPidMax; + float distance = 0.0F; + index.search(query.data(), 1, 1, &result, &distance); + EXPECT_EQ(result, 1U); + EXPECT_NEAR(distance, -99.0F, 1e-5F); +} + +TEST(IvfSearchTest, InnerProductRawRerankingUsesResidualNormForPruning) { + constexpr size_t kNum = 65; + constexpr size_t kDim = 64; + constexpr size_t kTopK = 1; + std::vector data(kNum * kDim); + std::vector centroids(2 * kDim, 0.0F); + std::vector clusters(kNum, 1); + std::array query{}; + query[0] = 1.0F; + centroids[0] = 100.0F; + centroids[kDim] = 50.0F; + + for (size_t id = 0; id < kNum; ++id) { + clusters[id] = id < 32 ? 0 : 1; + data[id * kDim] = id < 32 ? 10.0F + static_cast(id) * 0.01F : 0.0F; + for (size_t d = 1; d < kDim; ++d) { + data[id * kDim + d] = + std::sin(static_cast((id + 1) * (d + 3)) * 0.17F) * 20.0F; + } + } + data[32 * kDim] = 1000.0F; + + IVF index(kNum, kDim, 2, 32, METRIC_IP); + index.construct(data.data(), centroids.data(), clusters.data(), false, 1); + for (bool use_hacc : {false, true}) { + std::array ids{}; + std::array distances{}; + index.search(query.data(), kTopK, 2, ids.data(), distances.data(), use_hacc); + EXPECT_EQ(ids[0], 32U); + EXPECT_FLOAT_EQ(distances[0], -999.0F); + } +} + TEST(IvfPersistenceTest, ReloadsRawAndQuantizedStorage) { constexpr size_t kNum = 33; constexpr size_t kDim = 65; @@ -119,5 +268,94 @@ TEST(IvfPersistenceTest, ReloadsRawAndQuantizedStorage) { std::remove(path.c_str()); } +TEST(IvfPersistenceTest, FailedLoadPreservesExistingIndex) { + constexpr size_t kTargetNum = 2; + constexpr size_t kTargetDim = 64; + std::vector target_data(kTargetNum * kTargetDim, 1.0F); + std::vector target_centroid(kTargetDim, 0.0F); + std::array target_clusters{0, 0}; + std::fill( + target_data.begin() + static_cast(kTargetDim), target_data.end(), 2.0F + ); + const std::string path = ::testing::TempDir() + "rabitq_ivf_truncated.index"; + + IVF target(kTargetNum, kTargetDim, 1, 32, METRIC_IP, RotatorType::MatrixRotator); + target.construct( + target_data.data(), target_centroid.data(), target_clusters.data(), false, 1 + ); + std::array expected_ids{}; + std::array expected_distances{}; + target.search( + target_centroid.data(), + kTargetNum, + 1, + expected_ids.data(), + expected_distances.data() + ); + + constexpr size_t kSourceNum = 33; + constexpr size_t kSourceDim = 65; + std::vector source_data(kSourceNum * kSourceDim, 0.25F); + std::vector source_centroid(kSourceDim, 0.5F); + std::vector source_clusters(kSourceNum, 0); + IVF source(kSourceNum, kSourceDim, 1, 4, METRIC_L2, RotatorType::FhtKacRotator); + source.construct( + source_data.data(), source_centroid.data(), source_clusters.data(), false, 1 + ); + source.save(path.c_str()); + + std::ifstream input(path, std::ios::binary); + const std::vector bytes( + (std::istreambuf_iterator(input)), std::istreambuf_iterator() + ); + ASSERT_GT(bytes.size(), 1U); + input.close(); + std::ofstream output(path, std::ios::binary | std::ios::trunc); + output.write(bytes.data(), static_cast(bytes.size() - 1)); + output.close(); + + EXPECT_ANY_THROW(target.load(path.c_str())); + EXPECT_EQ(target.max_elements(), kTargetNum); + EXPECT_EQ(target.dimension(), kTargetDim); + EXPECT_EQ(target.num_clusters(), 1U); + EXPECT_EQ(target.nbits(), 32U); + EXPECT_EQ(target.metric_type(), METRIC_IP); + EXPECT_EQ(target.rotator_type(), RotatorType::MatrixRotator); + + std::array actual_ids{}; + std::array actual_distances{}; + target.search( + target_centroid.data(), kTargetNum, 1, actual_ids.data(), actual_distances.data() + ); + EXPECT_EQ(actual_ids, expected_ids); + EXPECT_EQ(actual_distances, expected_distances); + + std::remove(path.c_str()); +} + +TEST(IvfPersistenceTest, RejectsPointIdsUsingTheSearchBufferMarker) { + constexpr size_t kNum = 33; + constexpr size_t kDim = 64; + std::vector data(kNum * kDim, 0.25F); + std::vector centroid(kDim, 0.0F); + std::vector clusters(kNum, 0); + const std::string path = ::testing::TempDir() + "rabitq_ivf_bad_id.index"; + + IVF source(kNum, kDim, 1, 4); + source.construct(data.data(), centroid.data(), clusters.data(), false, 1); + source.save(path.c_str()); + + std::fstream file(path, std::ios::binary | std::ios::in | std::ios::out); + ASSERT_TRUE(file.is_open()); + file.seekp(-static_cast(sizeof(PID)), std::ios::end); + const PID marked_id = buffer::kSearchBufferCheckedMask; + file.write(reinterpret_cast(&marked_id), sizeof(marked_id)); + file.close(); + + IVF loaded; + EXPECT_THROW(loaded.load(path.c_str()), std::runtime_error); + std::remove(path.c_str()); +} + } // namespace } // namespace rabitqlib::ivf diff --git a/tests/unit/rabitqlib/index/qg_test.cpp b/tests/unit/rabitqlib/index/qg_test.cpp index 2fd012c..c47abe3 100644 --- a/tests/unit/rabitqlib/index/qg_test.cpp +++ b/tests/unit/rabitqlib/index/qg_test.cpp @@ -1,21 +1,74 @@ +#include "rabitqlib/index/symqg/qg.hpp" + #include #include #include #include +#include #include #include +#include +#include +#include +#include #include +#include #include #include #include +#include #include +#include "rabitqlib/defines.hpp" +#include "rabitqlib/fastscan/fastscan.hpp" +#include "rabitqlib/index/estimator.hpp" +#include "rabitqlib/index/lut.hpp" +#include "rabitqlib/index/query.hpp" +#include "rabitqlib/index/symqg/detail/pipnn.hpp" #include "rabitqlib/index/symqg/qg_builder.hpp" +#include "rabitqlib/quantization/data_layout.hpp" +#include "rabitqlib/quantization/rabitq.hpp" #include "rabitqlib/utils/cpu_features.hpp" +#include "rabitqlib/utils/rotator.hpp" +#include "rabitqlib/utils/space.hpp" namespace rabitqlib::symqg { struct QGConstructionTestAccess { + static void check_contiguous_rows(QuantizedGraph& graph) { + const size_t vector_bytes = + graph.is_quantized() + ? ExDataMap::data_bytes(graph.padded_dim_, graph.quantization_bits_) + : graph.dim_ * sizeof(float); + const size_t batch_bytes = QGBatchDataMap::data_bytes(graph.padded_dim_) * + (graph.degree_bound_ / fastscan::kBatchSize); + const size_t row_bytes = + vector_bytes + batch_bytes + (graph.degree_bound_ * sizeof(PID)); + const char* base = graph.get_row_data(0); + for (PID id = 0; id < graph.num_points_; ++id) { + const char* row = graph.get_row_data(id); + EXPECT_EQ(row, base + (id * row_bytes)); + EXPECT_EQ(graph.get_batch_data(id), row + vector_bytes); + if (graph.is_quantized()) { + EXPECT_EQ(graph.get_quantized_vector(id), row); + } else { + EXPECT_EQ(reinterpret_cast(graph.get_vector(id)), row); + graph.get_vector(id)[graph.dim_ - 1] = static_cast(id); + } + graph.get_neighbors(id)[0] = id; + PID stored_id = kPidMax; + std::memcpy(&stored_id, row + vector_bytes + batch_bytes, sizeof(stored_id)); + EXPECT_EQ(stored_id, id); + } + if (!graph.is_quantized()) { + for (PID id = 0; id < graph.num_points_; ++id) { + EXPECT_FLOAT_EQ( + graph.get_vector(id)[graph.dim_ - 1], static_cast(id) + ); + } + } + } + static QGBuilder from_graph( QuantizedGraph& graph, uint32_t ef, @@ -31,7 +84,9 @@ struct QGConstructionTestAccess { static auto codes(const QuantizedGraph& graph) { std::vector result; for (PID id = 0; id < graph.num_points_; ++id) { - const char* code = graph.get_quantized_vector(id); + const char* code = graph.is_quantized() + ? graph.get_quantized_vector(id) + : reinterpret_cast(graph.get_vector(id)); result.insert(result.end(), code, code + graph.batch_data_offset_); } return result; @@ -55,9 +110,37 @@ struct QGConstructionTestAccess { } } static void search(QGBuilder& builder) { builder.search_new_neighbors(false); } - static const PID* encoded_neighbors(const QuantizedGraph& graph, PID id) { + static auto encoded_neighbors(const QuantizedGraph& graph, PID id) { return graph.get_neighbors(id); } + static void set_encoded_neighbor( + QuantizedGraph& graph, PID source, size_t lane, PID target + ) { + graph.get_neighbors(source)[lane] = target; + } + static void copy_vectors( + QuantizedGraph& graph, const float* data, size_t threads + ) { + graph.copy_vectors(data, threads); + } + static void update( + QuantizedGraph& graph, + PID source, + const std::vector>& neighbors + ) { + graph.update_qg(source, neighbors); + } + static void fill_batch_factors(QuantizedGraph& graph, PID source, float value) { + QGBatchDataMap batch(graph.get_batch_data(source), graph.padded_dim_); + std::fill_n(batch.f_add(), fastscan::kBatchSize, value); + std::fill_n(batch.f_rescale(), fastscan::kBatchSize, value); + } + static std::pair batch_factors( + const QuantizedGraph& graph, PID source, size_t lane + ) { + ConstQGBatchDataMap batch(graph.get_batch_data(source), graph.padded_dim_); + return {batch.f_add()[lane], batch.f_rescale()[lane]}; + } static std::array estimate( const QuantizedGraph& graph, PID source, PID target ) { @@ -94,6 +177,19 @@ struct QGConstructionTestAccess { namespace { +TEST(QuantizedGraphLayoutTest, KeepsVectorsCodesAndNeighborsInContiguousRows) { + for (size_t bits : {0U, 4U, 8U}) { + SCOPED_TRACE(bits); + QuantizedGraph graph( + 33, 65, 32, METRIC_L2, RotatorType::FhtKacRotator, bits + ); + QGConstructionTestAccess::check_contiguous_rows(graph); + } +} + +static_assert(std::is_copy_constructible_v>); +static_assert(std::is_move_constructible_v>); + static_assert( !std::is_constructible_v< QGBuilder, @@ -264,8 +360,10 @@ TEST(QGConstructionTest, DefaultsToPipnnInitialization) { std::sort(expected.begin(), expected.end()); ASSERT_EQ(QGConstructionTestAccess::degrees(builder)[i], expected.size()); EXPECT_TRUE(QGConstructionTestAccess::neighbors(builder)[i].empty()); - const PID* actual = QGConstructionTestAccess::encoded_neighbors(graph, i); - EXPECT_TRUE(std::equal(expected.begin(), expected.end(), actual)); + const auto actual = QGConstructionTestAccess::encoded_neighbors(graph, i); + for (size_t j = 0; j < expected.size(); ++j) { + EXPECT_EQ(actual[j], expected[j]); + } } builder.build(); EXPECT_FLOAT_EQ(builder.avg_degree(), kDegree); @@ -295,6 +393,64 @@ TEST(QGConstructionTest, SupportsExplicitRandomInitialization) { ); } +TEST(QGConstructionTest, RejectsNullDataForEveryInitializationMode) { + QuantizedGraph graph(33, 64, 32); + EXPECT_THROW( + (QGBuilder(graph, 32, nullptr, 1, QGInitialization::PiPNN)), std::invalid_argument + ); + EXPECT_THROW( + (QGBuilder(graph, 32, nullptr, 1, QGInitialization::Random)), std::invalid_argument + ); +} + +TEST(QGConstructionTest, UsesExplicitThreadCountsWithoutChangingCallerState) { + if (!cpu::has_avx2()) { + GTEST_SKIP() << "FastScan requires AVX2/FMA"; + } + constexpr size_t kCount = 33, kDim = 64; + std::vector data(kCount * kDim, 0.25F); + const int caller_threads = omp_get_max_threads(); + + QuantizedGraph first(kCount, kDim, 32); + QuantizedGraph second(kCount, kDim, 32); + QGBuilder first_builder(first, 32, data.data(), 1, QGInitialization::Random); + EXPECT_EQ(omp_get_max_threads(), caller_threads); + QGBuilder second_builder(second, 32, data.data(), 2, QGInitialization::PiPNN); + EXPECT_EQ(omp_get_max_threads(), caller_threads); + + first_builder.build(2); + second_builder.build(2); + EXPECT_EQ(omp_get_max_threads(), caller_threads); +} + +TEST(QGConstructionTest, InitializesUnusedPartialBatchFactors) { + if (!cpu::has_avx2()) { + GTEST_SKIP() << "FastScan requires AVX2/FMA"; + } + constexpr size_t kCount = 33, kDim = 64; + std::vector data(kCount * kDim); + for (size_t i = 0; i < data.size(); ++i) { + data[i] = std::sin(static_cast(i) * 0.17F); + } + QuantizedGraph graph(kCount, kDim, 32); + QGConstructionTestAccess::copy_vectors(graph, data.data(), 1); + QGConstructionTestAccess::fill_batch_factors( + graph, 0, std::numeric_limits::quiet_NaN() + ); + std::vector> neighbors; + neighbors.emplace_back(1, 0.0F); + QGConstructionTestAccess::update(graph, 0, neighbors); + + const auto active = QGConstructionTestAccess::batch_factors(graph, 0, 0); + EXPECT_TRUE(std::isfinite(active.first)); + EXPECT_TRUE(std::isfinite(active.second)); + for (size_t lane = 1; lane < fastscan::kBatchSize; ++lane) { + const auto factors = QGConstructionTestAccess::batch_factors(graph, 0, lane); + EXPECT_FLOAT_EQ(factors.first, 0.0F); + EXPECT_FLOAT_EQ(factors.second, 0.0F); + } +} + TEST(QGConstructionTest, RefinesPartialSeedOnceAfterReleasingInputs) { if (!cpu::has_avx2()) { GTEST_SKIP() << "FastScan requires AVX2/FMA"; @@ -463,11 +619,145 @@ TEST(QuantizedGraphConfigurationTest, RejectsUnsupportedMetric) { ); } +TEST(QuantizedGraphConfigurationTest, RejectsZeroDimension) { + EXPECT_THROW( + (QuantizedGraph(33, 0, 32, METRIC_L2, RotatorType::MatrixRotator)), + std::invalid_argument + ); +} + +TEST(QuantizedGraphConfigurationTest, RejectsOutOfRangeEntryPoint) { + QuantizedGraph graph(33, 64, 32); + EXPECT_NO_THROW(graph.set_ep(32)); + EXPECT_THROW(graph.set_ep(33), std::invalid_argument); + EXPECT_EQ(graph.entry_point(), 32U); +} + +TEST(QuantizedGraphPersistenceTest, RejectsMalformedPayloadWithoutChangingTarget) { + constexpr size_t kNumPoints = 33; + constexpr size_t kDim = 64; + constexpr size_t kDegree = 32; + std::vector data(kNumPoints * kDim, 0.25F); + QuantizedGraph source( + kNumPoints, kDim, kDegree, METRIC_L2, RotatorType::MatrixRotator, 4 + ); + QGBuilder builder(source, kDegree, data.data(), 1); + builder.build(2); + + const std::string path = ::testing::TempDir() + "rabitq_qg_malformed.index"; + QuantizedGraph target(65, kDim, kDegree, METRIC_IP); + + source.save(path.c_str()); + std::filesystem::resize_file(path, std::filesystem::file_size(path) - 1); + EXPECT_THROW(target.load(path.c_str()), std::runtime_error); + EXPECT_EQ(target.num_vertices(), 65U); + EXPECT_EQ(target.metric_type(), METRIC_IP); + + source.save(path.c_str()); + { + std::fstream file(path, std::ios::binary | std::ios::in | std::ios::out); + ASSERT_TRUE(file.is_open()); + constexpr std::streamoff kPaddedDimensionOffset = + sizeof(uint64_t) + sizeof(uint32_t) + (3 * sizeof(size_t)); + file.seekp(kPaddedDimensionOffset); + const size_t invalid_padded_dim = kDim * 2; + file.write( + reinterpret_cast(&invalid_padded_dim), sizeof(invalid_padded_dim) + ); + ASSERT_TRUE(file.good()); + } + EXPECT_THROW(target.load(path.c_str()), std::runtime_error); + EXPECT_EQ(target.num_vertices(), 65U); + EXPECT_EQ(target.metric_type(), METRIC_IP); + + source.save(path.c_str()); + { + std::fstream file(path, std::ios::binary | std::ios::in | std::ios::out); + ASSERT_TRUE(file.is_open()); + constexpr std::streamoff kPointCountOffset = sizeof(uint64_t) + sizeof(uint32_t); + file.seekp(kPointCountOffset); + const size_t invalid_point_count = std::numeric_limits::max(); + file.write( + reinterpret_cast(&invalid_point_count), sizeof(invalid_point_count) + ); + ASSERT_TRUE(file.good()); + } + EXPECT_THROW(target.load(path.c_str()), std::invalid_argument); + EXPECT_EQ(target.num_vertices(), 65U); + EXPECT_EQ(target.metric_type(), METRIC_IP); + + if (std::filesystem::exists("/dev/full")) { + EXPECT_THROW(source.save("/dev/full"), std::ios_base::failure); + } + + QGConstructionTestAccess::set_encoded_neighbor(source, 0, 0, kNumPoints); + source.save(path.c_str()); + EXPECT_THROW(target.load(path.c_str()), std::runtime_error); + EXPECT_EQ(target.num_vertices(), 65U); + EXPECT_EQ(target.metric_type(), METRIC_IP); + + std::remove(path.c_str()); +} + TEST(QuantizedGraphLifecycleTest, DestroysConcreteRotatorThroughBasePointer) { QuantizedGraph graph(33, 64, 32, METRIC_L2, RotatorType::MatrixRotator); EXPECT_EQ(graph.num_vertices(), 33U); } +TEST(QuantizedGraphLifecycleTest, RejectsSearchAndSaveBeforeBuild) { + const std::string path = ::testing::TempDir() + "rabitq_qg_unbuilt.index"; + std::remove(path.c_str()); + std::array query{}; + std::array ids{}; + std::array distances{}; + + QuantizedGraph empty; + EXPECT_THROW(empty.save(path.c_str()), std::logic_error); + EXPECT_THROW( + empty.search(query.data(), 1, ids.data(), distances.data()), std::logic_error + ); + + QuantizedGraph configured(33, 64, 32); + configured.set_ef(1); + EXPECT_THROW(configured.save(path.c_str()), std::logic_error); + EXPECT_THROW( + configured.search(query.data(), 1, ids.data(), distances.data()), std::logic_error + ); + EXPECT_FALSE(std::filesystem::exists(path)); + std::remove(path.c_str()); +} + +TEST(QuantizedGraphLifecycleTest, BuilderDoesNotPublishPartialGraph) { + if (!cpu::has_avx2()) { + GTEST_SKIP() << "FastScan requires AVX2/FMA"; + } + constexpr size_t kNumPoints = 33; + constexpr size_t kDim = 64; + constexpr size_t kDegree = 32; + std::vector data(kNumPoints * kDim, 0.25F); + std::array query{}; + PID result = 0; + float distance = 0; + + for (const auto init : {QGInitialization::Random, QGInitialization::PiPNN}) { + SCOPED_TRACE(static_cast(init)); + const std::string path = ::testing::TempDir() + "rabitq_qg_partial.index"; + std::remove(path.c_str()); + QuantizedGraph graph(kNumPoints, kDim, kDegree); + QGBuilder builder(graph, kDegree, data.data(), 1, init); + graph.set_ef(1); + EXPECT_THROW(graph.save(path.c_str()), std::logic_error); + EXPECT_THROW(graph.search(query.data(), 1, &result, &distance), std::logic_error); + EXPECT_FALSE(std::filesystem::exists(path)); + + builder.build(2); + EXPECT_NO_THROW(graph.search(query.data(), 1, &result, &distance)); + EXPECT_NO_THROW(graph.save(path.c_str())); + EXPECT_TRUE(std::filesystem::exists(path)); + std::remove(path.c_str()); + } +} + TEST(QGBuilderMetricTest, UsesInnerProductDistanceToChooseEntryPoint) { constexpr size_t kNumPoints = 33; constexpr size_t kDim = 64; @@ -561,8 +851,8 @@ TEST(QGQuantTest, SearchesAndRoundTripsFourAndEightBitIndexes) { ::testing::TempDir() + "rabitq_qg_quant_" + std::to_string(bits) + ".index"; graph.save(path.c_str()); QuantizedGraph loaded; - loaded.load(path.c_str()); loaded.set_ef(kNumPoints); + loaded.load(path.c_str()); EXPECT_TRUE(loaded.is_quantized()); EXPECT_EQ(loaded.quantization_bits(), bits); @@ -577,6 +867,69 @@ TEST(QGQuantTest, SearchesAndRoundTripsFourAndEightBitIndexes) { } } +TEST(QGSearchTest, RejectsInvalidKAndEfInsteadOfReturningPartialResults) { + if (!cpu::has_avx2()) { + GTEST_SKIP() << "FastScan requires AVX2/FMA"; + } + constexpr size_t kNumPoints = 33, kDim = 64, kDegree = 32; + std::vector data(kNumPoints * kDim); + for (size_t i = 0; i < data.size(); ++i) { + data[i] = std::sin(static_cast(i) * 0.11F); + } + QuantizedGraph graph(kNumPoints, kDim, kDegree); + QGBuilder builder(graph, kDegree, data.data(), 1, QGInitialization::Random); + builder.build(2); + + std::array ids{}; + std::array distances{}; + EXPECT_THROW(graph.set_ef(0), std::invalid_argument); + graph.set_ef(4); + EXPECT_THROW( + graph.search(data.data(), 5, ids.data(), distances.data()), std::invalid_argument + ); + graph.set_ef(kNumPoints); + EXPECT_THROW( + graph.search(data.data(), 0, ids.data(), distances.data()), std::invalid_argument + ); + EXPECT_THROW( + graph.search( + data.data(), static_cast(kNumPoints + 1), ids.data(), distances.data() + ), + std::invalid_argument + ); + EXPECT_THROW( + graph.search(nullptr, 1, ids.data(), distances.data()), std::invalid_argument + ); + EXPECT_THROW( + graph.search(data.data(), 1, nullptr, distances.data()), std::invalid_argument + ); + EXPECT_THROW(graph.search(data.data(), 1, ids.data(), nullptr), std::invalid_argument); + + graph.search( + data.data(), static_cast(kNumPoints), ids.data(), distances.data() + ); + for (size_t i = 0; i < kNumPoints; ++i) { + EXPECT_LT(ids[i], kNumPoints); + EXPECT_TRUE(std::isfinite(distances[i])); + } + + for (PID source = 0; source < kNumPoints; ++source) { + for (size_t lane = 0; lane < kDegree; ++lane) { + QGConstructionTestAccess::set_encoded_neighbor(graph, source, lane, 0); + } + } + graph.set_ef(3); + ids.fill(kPidMax); + distances.fill(-123.0F); + EXPECT_THROW( + graph.search(data.data(), 3, ids.data(), distances.data()), std::runtime_error + ); + EXPECT_TRUE(std::all_of(ids.begin(), ids.end(), [](PID id) { return id == kPidMax; })); + EXPECT_TRUE(std::all_of(distances.begin(), distances.end(), [](float distance) { + return distance == -123.0F; + })); +} + TEST(QGSearchTest, ParallelQueriesMatchSerialAcrossIndexesAndSettings) { constexpr size_t kNumQueries = 9; constexpr size_t kTopK = 5; diff --git a/tests/unit/rabitqlib/quantization/data_layout_test.cpp b/tests/unit/rabitqlib/quantization/data_layout_test.cpp new file mode 100644 index 0000000..c7b6b04 --- /dev/null +++ b/tests/unit/rabitqlib/quantization/data_layout_test.cpp @@ -0,0 +1,184 @@ +#include "rabitqlib/quantization/data_layout.hpp" + +#include + +#include +#include +#include +#include +#include +#include + +#include "rabitqlib/fastscan/fastscan.hpp" +#include "rabitqlib/quantization/rabitq.hpp" + +namespace rabitqlib { +namespace { + +float load_float(const char* data) { + float value; + std::memcpy(&value, data, sizeof(value)); + return value; +} + +TEST(DataLayoutTest, BatchFactorsKeepPackedOffsetsOnUnalignedStorage) { + constexpr size_t kDim = 64; + constexpr size_t kCodeBytes = kDim * fastscan::kBatchSize / 8; + constexpr size_t kDataBytes = kCodeBytes + (3 * fastscan::kBatchSize * sizeof(float)); + const size_t data_bytes = BatchDataMap::data_bytes(kDim); + ASSERT_EQ(data_bytes, kCodeBytes + (3 * fastscan::kBatchSize * sizeof(float))); + + alignas(float) std::array storage; + storage.fill(char{0x5a}); + char* data = storage.data() + 1; + ASSERT_NE( + reinterpret_cast(data + kCodeBytes) % alignof(float), uintptr_t{0} + ); + BatchDataMap batch(data, kDim); + batch.f_add()[0] = 1.25F; + batch.f_rescale()[0] = -2.5F; + batch.f_error()[fastscan::kBatchSize - 1] = 3.75F; + + ConstBatchDataMap stored(data, kDim); + EXPECT_FLOAT_EQ(stored.f_add()[0], 1.25F); + EXPECT_FLOAT_EQ(stored.f_rescale()[0], -2.5F); + EXPECT_FLOAT_EQ(stored.f_error()[fastscan::kBatchSize - 1], 3.75F); + EXPECT_FLOAT_EQ(load_float(data + kCodeBytes), 1.25F); + EXPECT_FLOAT_EQ( + load_float(data + kCodeBytes + (fastscan::kBatchSize * sizeof(float))), -2.5F + ); + EXPECT_FLOAT_EQ( + load_float(data + kCodeBytes + ((3 * fastscan::kBatchSize - 1) * sizeof(float))), + 3.75F + ); + EXPECT_EQ(storage.front(), char{0x5a}); + EXPECT_EQ(storage.back(), char{0x5a}); +} + +TEST(DataLayoutTest, QgBatchFactorsKeepPackedOffsetsOnUnalignedStorage) { + constexpr size_t kDim = 64; + constexpr size_t kCodeBytes = kDim * fastscan::kBatchSize / 8; + constexpr size_t kDataBytes = kCodeBytes + (2 * fastscan::kBatchSize * sizeof(float)); + const size_t data_bytes = QGBatchDataMap::data_bytes(kDim); + ASSERT_EQ(data_bytes, kCodeBytes + (2 * fastscan::kBatchSize * sizeof(float))); + + alignas(float) std::array storage{}; + char* data = storage.data() + 1; + ASSERT_NE( + reinterpret_cast(data + kCodeBytes) % alignof(float), uintptr_t{0} + ); + QGBatchDataMap batch(data, kDim); + std::fill_n(batch.f_add(), fastscan::kBatchSize, 4.25F); + std::fill_n(batch.f_rescale(), fastscan::kBatchSize, -5.5F); + + ConstQGBatchDataMap stored(data, kDim); + EXPECT_FLOAT_EQ(stored.f_add()[fastscan::kBatchSize - 1], 4.25F); + EXPECT_FLOAT_EQ(stored.f_rescale()[fastscan::kBatchSize - 1], -5.5F); + EXPECT_FLOAT_EQ(load_float(data + kCodeBytes), 4.25F); + EXPECT_FLOAT_EQ( + load_float(data + kCodeBytes + (fastscan::kBatchSize * sizeof(float))), -5.5F + ); +} + +TEST(DataLayoutTest, SingleCodeFactorsKeepPackedOffsetsOnUnalignedStorage) { + constexpr size_t kDim = 64; + constexpr size_t kBits = 3; + constexpr size_t kCodeBytes = kDim * kBits / 8; + + constexpr size_t kExBytes = kCodeBytes + (2 * sizeof(float)); + alignas(float) std::array ex_storage{}; + char* ex_data = ex_storage.data() + 1; + ASSERT_NE( + reinterpret_cast(ex_data + kCodeBytes) % alignof(float), uintptr_t{0} + ); + ExDataMap ex(ex_data, kDim, kBits); + ex.f_add_ex() = 6.25F; + ex.f_rescale_ex() = -7.5F; + ConstExDataMap stored_ex(ex_data, kDim, kBits); + EXPECT_FLOAT_EQ(stored_ex.f_add_ex(), 6.25F); + EXPECT_FLOAT_EQ(stored_ex.f_rescale_ex(), -7.5F); + EXPECT_FLOAT_EQ(load_float(ex_data + kCodeBytes), 6.25F); + EXPECT_FLOAT_EQ(load_float(ex_data + kCodeBytes + sizeof(float)), -7.5F); + + constexpr size_t kBaseBytes = kCodeBytes + (3 * sizeof(float)); + alignas(float) std::array base_storage{}; + char* base_data = base_storage.data() + 1; + ASSERT_NE( + reinterpret_cast(base_data + kCodeBytes) % alignof(float), uintptr_t{0} + ); + BaseDataMap base(base_data, kDim, kBits); + base.f_add() = 8.25F; + base.f_rescale() = -9.5F; + base.f_error() = 10.75F; + ConstBaseDataMap stored_base(base_data, kDim, kBits); + EXPECT_FLOAT_EQ(stored_base.f_add(), 8.25F); + EXPECT_FLOAT_EQ(stored_base.f_rescale(), -9.5F); + EXPECT_FLOAT_EQ(stored_base.f_error(), 10.75F); + EXPECT_FLOAT_EQ(load_float(base_data + kCodeBytes), 8.25F); + EXPECT_FLOAT_EQ(load_float(base_data + kCodeBytes + sizeof(float)), -9.5F); + EXPECT_FLOAT_EQ(load_float(base_data + kCodeBytes + (2 * sizeof(float))), 10.75F); + + constexpr size_t kBinCodeBytes = kDim / 8; + constexpr size_t kBinBytes = kBinCodeBytes + (3 * sizeof(float)); + alignas(uint64_t) std::array bin_storage{}; + char* bin_data = bin_storage.data() + 1; + ASSERT_NE(reinterpret_cast(bin_data) % alignof(uint64_t), uintptr_t{0}); + ASSERT_NE( + reinterpret_cast(bin_data + kBinCodeBytes) % alignof(float), uintptr_t{0} + ); + BinDataMap bin(bin_data, kDim); + static_assert(std::is_same_v); + bin.bin_code()[0] = 0xa5; + bin.f_add() = 11.25F; + bin.f_rescale() = -12.5F; + bin.f_error() = 13.75F; + ConstBinDataMap stored_bin(bin_data, kDim); + static_assert(std::is_same_v); + EXPECT_EQ(stored_bin.bin_code()[0], uint8_t{0xa5}); + EXPECT_FLOAT_EQ(stored_bin.f_add(), 11.25F); + EXPECT_FLOAT_EQ(stored_bin.f_rescale(), -12.5F); + EXPECT_FLOAT_EQ(stored_bin.f_error(), 13.75F); + EXPECT_FLOAT_EQ(load_float(bin_data + kBinCodeBytes), 11.25F); + EXPECT_FLOAT_EQ(load_float(bin_data + kBinCodeBytes + sizeof(float)), -12.5F); + EXPECT_FLOAT_EQ(load_float(bin_data + kBinCodeBytes + (2 * sizeof(float))), 13.75F); +} + +TEST(DataLayoutTest, UnalignedSingleCodePreservesUint64PackedRepresentation) { + constexpr size_t kDim = 64; + constexpr size_t kCodeBytes = kDim / 8; + constexpr size_t kDataBytes = kCodeBytes + (3 * sizeof(float)); + std::array data{}; + std::array centroid{}; + for (size_t i = 0; i < kDim; ++i) { + data[i] = static_cast(static_cast(i % 7) - 3); + centroid[i] = static_cast(static_cast(i % 5) - 2) * 0.25F; + } + + uint64_t expected_code = 0; + float expected_add = 0; + float expected_rescale = 0; + float expected_error = 0; + quant::quantize_compact_one_bit( + data.data(), + centroid.data(), + kDim, + &expected_code, + expected_add, + expected_rescale, + expected_error + ); + + alignas(uint64_t) std::array storage{}; + char* packed = storage.data() + 1; + ASSERT_NE(reinterpret_cast(packed) % alignof(uint64_t), uintptr_t{0}); + quant::quantize_compact_one_bit(data.data(), centroid.data(), kDim, packed); + + ConstBinDataMap stored(packed, kDim); + EXPECT_EQ(std::memcmp(stored.bin_code(), &expected_code, sizeof(expected_code)), 0); + EXPECT_FLOAT_EQ(stored.f_add(), expected_add); + EXPECT_FLOAT_EQ(stored.f_rescale(), expected_rescale); + EXPECT_FLOAT_EQ(stored.f_error(), expected_error); +} + +} // namespace +} // namespace rabitqlib diff --git a/tests/unit/rabitqlib/utils/buffer_test.cpp b/tests/unit/rabitqlib/utils/buffer_test.cpp new file mode 100644 index 0000000..0222a5f --- /dev/null +++ b/tests/unit/rabitqlib/utils/buffer_test.cpp @@ -0,0 +1,39 @@ +#include "rabitqlib/utils/buffer.hpp" + +#include + +#include +#include +#include + +#include "rabitqlib/defines.hpp" + +namespace rabitqlib::buffer { +namespace { + +TEST(SearchBufferTest, RejectsCapacityWhoseSentinelWouldOverflow) { + EXPECT_THROW( + (SearchBuffer(std::numeric_limits::max())), std::length_error + ); + + SearchBuffer buffer; + EXPECT_TRUE(buffer.is_full()); + EXPECT_FALSE(buffer.has_next()); + EXPECT_EQ(buffer.size(), 0U); + buffer.insert(7, 1.0F); + EXPECT_EQ(buffer.size(), 0U); + EXPECT_THROW(buffer.resize(std::numeric_limits::max()), std::length_error); + + SearchBuffer populated(2); + populated.insert(7, 1.0F); + EXPECT_THROW(populated.resize(std::numeric_limits::max()), std::length_error); + EXPECT_EQ(populated.size(), 1U); + PID result = 0; + float distance = 0; + populated.copy_results(&result, &distance); + EXPECT_EQ(result, 7U); + EXPECT_FLOAT_EQ(distance, 1.0F); +} + +} // namespace +} // namespace rabitqlib::buffer diff --git a/tests/unit/rabitqlib/utils/cpu_features_test.cpp b/tests/unit/rabitqlib/utils/cpu_features_test.cpp index 974ce60..37829c0 100644 --- a/tests/unit/rabitqlib/utils/cpu_features_test.cpp +++ b/tests/unit/rabitqlib/utils/cpu_features_test.cpp @@ -2,7 +2,22 @@ #include -TEST(CpuFeatures, returns_stable_result) { +#include + +namespace { + +rabitqlib::cpu::Features all_hardware_features() { + return { + true, + true, + true, + true, + true, + true, + }; +} + +TEST(CpuFeatures, ReturnsStableResult) { const auto& first = rabitqlib::cpu::features(); const auto& second = rabitqlib::cpu::features(); @@ -12,3 +27,68 @@ TEST(CpuFeatures, returns_stable_result) { rabitqlib::cpu::has_avx512_core() && first.avx512vpopcntdq ); } + +TEST(CpuFeatures, RequiresOsManagedAvxState) { + constexpr uint64_t kAvxState = 0x6; + const auto hardware = all_hardware_features(); + + auto usable = + rabitqlib::cpu::detail::filter_usable_features(hardware, true, false, kAvxState); + EXPECT_FALSE(usable.avx2); + EXPECT_FALSE(usable.fma); + EXPECT_FALSE(usable.avx512f); + + usable = + rabitqlib::cpu::detail::filter_usable_features(hardware, false, true, kAvxState); + EXPECT_FALSE(usable.avx2); + EXPECT_FALSE(usable.fma); + EXPECT_FALSE(usable.avx512f); + + usable = rabitqlib::cpu::detail::filter_usable_features(hardware, true, true, 0); + EXPECT_FALSE(usable.avx2); + EXPECT_FALSE(usable.fma); + EXPECT_FALSE(usable.avx512f); +} + +TEST(CpuFeatures, EnablesAvx2WithoutAvx512State) { + constexpr uint64_t kAvxState = 0x6; + const auto usable = rabitqlib::cpu::detail::filter_usable_features( + all_hardware_features(), true, true, kAvxState + ); + + EXPECT_TRUE(usable.avx2); + EXPECT_TRUE(usable.fma); + EXPECT_FALSE(usable.avx512f); + EXPECT_FALSE(usable.avx512bw); + EXPECT_FALSE(usable.avx512dq); + EXPECT_FALSE(usable.avx512vpopcntdq); +} + +TEST(CpuFeatures, EnablesAvx512OnlyWithCompleteAvx512State) { + constexpr uint64_t kAvx512State = 0xe6; + const auto usable = rabitqlib::cpu::detail::filter_usable_features( + all_hardware_features(), true, true, kAvx512State + ); + + EXPECT_TRUE(usable.avx2); + EXPECT_TRUE(usable.fma); + EXPECT_TRUE(usable.avx512f); + EXPECT_TRUE(usable.avx512bw); + EXPECT_TRUE(usable.avx512dq); + EXPECT_TRUE(usable.avx512vpopcntdq); + + for (const uint64_t state_bit : + {uint64_t{1} << 5, uint64_t{1} << 6, uint64_t{1} << 7}) { + const auto incomplete = rabitqlib::cpu::detail::filter_usable_features( + all_hardware_features(), true, true, kAvx512State & ~state_bit + ); + EXPECT_TRUE(incomplete.avx2); + EXPECT_TRUE(incomplete.fma); + EXPECT_FALSE(incomplete.avx512f); + EXPECT_FALSE(incomplete.avx512bw); + EXPECT_FALSE(incomplete.avx512dq); + EXPECT_FALSE(incomplete.avx512vpopcntdq); + } +} + +} // namespace diff --git a/tests/unit/rabitqlib/utils/io_test.cpp b/tests/unit/rabitqlib/utils/io_test.cpp new file mode 100644 index 0000000..1aa3a9d --- /dev/null +++ b/tests/unit/rabitqlib/utils/io_test.cpp @@ -0,0 +1,110 @@ +#include "rabitqlib/utils/io.hpp" + +#include + +#include +#include +#include +#include +#include +#include + +#include "rabitqlib/defines.hpp" + +namespace rabitqlib { +namespace { + +template +void write_value(std::ofstream& output, const T& value) { + output.write(reinterpret_cast(&value), sizeof(value)); +} + +TEST(VectorIoTest, LoadsCompleteConsistentRecords) { + const std::string path = ::testing::TempDir() + "rabitq_valid.fvecs"; + { + std::ofstream output(path, std::ios::binary); + const uint32_t cols = 2; + const float values[] = {1.0F, 2.0F, 3.0F, 4.0F}; + write_value(output, cols); + output.write(reinterpret_cast(values), 2 * sizeof(float)); + write_value(output, cols); + output.write(reinterpret_cast(values + 2), 2 * sizeof(float)); + } + + RowMajorMatrix matrix; + load_vecs(path.c_str(), matrix); + ASSERT_EQ(matrix.rows(), 2); + ASSERT_EQ(matrix.cols(), 2); + EXPECT_FLOAT_EQ(matrix(0, 0), 1.0F); + EXPECT_FLOAT_EQ(matrix(1, 1), 4.0F); + std::remove(path.c_str()); +} + +TEST(VectorIoTest, RejectsInconsistentAndTruncatedRecordsWithoutReplacingOutput) { + const std::string path = ::testing::TempDir() + "rabitq_invalid.fvecs"; + RowMajorMatrix matrix(1, 1); + matrix(0, 0) = 7.0F; + + { + std::ofstream output(path, std::ios::binary); + const uint32_t cols = 2; + const uint32_t wrong_cols = 3; + const float values[] = {1.0F, 2.0F, 3.0F, 4.0F}; + write_value(output, cols); + output.write(reinterpret_cast(values), 2 * sizeof(float)); + write_value(output, wrong_cols); + output.write(reinterpret_cast(values + 2), 2 * sizeof(float)); + } + EXPECT_THROW(load_vecs(path.c_str(), matrix), std::runtime_error); + ASSERT_EQ(matrix.rows(), 1); + EXPECT_FLOAT_EQ(matrix(0, 0), 7.0F); + + { + std::ofstream output(path, std::ios::binary | std::ios::trunc); + const uint32_t cols = 2; + const float value = 1.0F; + write_value(output, cols); + write_value(output, value); + } + EXPECT_THROW(load_vecs(path.c_str(), matrix), std::runtime_error); + ASSERT_EQ(matrix.rows(), 1); + EXPECT_FLOAT_EQ(matrix(0, 0), 7.0F); + std::remove(path.c_str()); +} + +TEST(BinaryMatrixIoTest, ValidatesPayloadBeforeReplacingOutput) { + const std::string path = ::testing::TempDir() + "rabitq_matrix.bin"; + RowMajorMatrix matrix(1, 1); + matrix(0, 0) = 7.0F; + + { + std::ofstream output(path, std::ios::binary); + const uint32_t rows = 2; + const uint32_t cols = 2; + const float values[] = {1.0F, 2.0F, 3.0F}; + write_value(output, rows); + write_value(output, cols); + output.write(reinterpret_cast(values), sizeof(values)); + } + EXPECT_THROW(load_bin(path.c_str(), matrix), std::runtime_error); + ASSERT_EQ(matrix.rows(), 1); + EXPECT_FLOAT_EQ(matrix(0, 0), 7.0F); + + { + std::ofstream output(path, std::ios::binary | std::ios::trunc); + const uint32_t rows = 2; + const uint32_t cols = 2; + const float values[] = {1.0F, 2.0F, 3.0F, 4.0F}; + write_value(output, rows); + write_value(output, cols); + output.write(reinterpret_cast(values), sizeof(values)); + } + load_bin(path.c_str(), matrix); + ASSERT_EQ(matrix.rows(), 2); + ASSERT_EQ(matrix.cols(), 2); + EXPECT_FLOAT_EQ(matrix(1, 1), 4.0F); + std::remove(path.c_str()); +} + +} // namespace +} // namespace rabitqlib diff --git a/tests/unit/rabitqlib/utils/mask_ip_test.cpp b/tests/unit/rabitqlib/utils/mask_ip_test.cpp index 0ca5869..3df3ab9 100644 --- a/tests/unit/rabitqlib/utils/mask_ip_test.cpp +++ b/tests/unit/rabitqlib/utils/mask_ip_test.cpp @@ -16,10 +16,12 @@ TEST(MaskIpX0Q, BackendsMatchScalarAcrossBlocksAndAlignments) { if (!cpu::has_avx2()) { GTEST_SKIP() << "Binary dot product tests require AVX2/FMA"; } - using Function = float (*)(const float*, const uint64_t*, size_t); - std::vector functions{simd::mask_ip_x0_q_avx2, mask_ip_x0_q}; + using Function = float (*)(const float*, const uint8_t*, size_t); + std::vector functions{ + static_cast(simd::mask_ip_x0_q_avx2), + static_cast(mask_ip_x0_q)}; if (cpu::has_avx512_core()) { - functions.push_back(simd::mask_ip_x0_q_avx512); + functions.push_back(static_cast(simd::mask_ip_x0_q_avx512)); } for (size_t dim : {0, 64, 128, 192, 256, 448, 576, 1024, 4096}) { @@ -50,8 +52,7 @@ TEST(MaskIpX0Q, BackendsMatchScalarAcrossBlocksAndAlignments) { if (dim != 0) { std::memcpy(storage.data() + offset, words.data(), dim / 8); } - const auto* codes = - reinterpret_cast(storage.data() + offset); + const auto* codes = storage.data() + offset; for (auto function : functions) { const float result = function(query.data() + 1, codes, dim); EXPECT_NEAR(result, expected, 2e-6 * std::max(1.0, sum_abs)); diff --git a/tests/unit/rabitqlib/utils/memory_test.cpp b/tests/unit/rabitqlib/utils/memory_test.cpp new file mode 100644 index 0000000..4785c29 --- /dev/null +++ b/tests/unit/rabitqlib/utils/memory_test.cpp @@ -0,0 +1,38 @@ +#include "rabitqlib/utils/memory.hpp" + +#include + +#include +#include +#include +#include + +#include "rabitqlib/utils/array.hpp" + +namespace rabitqlib::memory { +namespace { + +TEST(AlignedAllocatorTest, RejectsSizeThatOverflowsAlignmentRounding) { + AlignedAllocator allocator; + EXPECT_THROW( + (void)allocator.allocate(std::numeric_limits::max()), + std::bad_array_new_length + ); +} + +TEST(AlignedAllocationTest, RejectsSizeThatOverflowsAlignmentRounding) { + EXPECT_THROW( + (align_allocate<64, char>(std::numeric_limits::max())), + std::bad_array_new_length + ); +} + +TEST(ArrayTest, RejectsDimensionProductOverflow) { + EXPECT_THROW( + (Array(std::vector{std::numeric_limits::max(), 2})), + std::bad_array_new_length + ); +} + +} // namespace +} // namespace rabitqlib::memory diff --git a/tests/unit/rabitqlib/utils/rotator_test.cpp b/tests/unit/rabitqlib/utils/rotator_test.cpp index ec2d88a..9662377 100644 --- a/tests/unit/rabitqlib/utils/rotator_test.cpp +++ b/tests/unit/rabitqlib/utils/rotator_test.cpp @@ -3,13 +3,14 @@ #include #include +#include +#include #include -#include #include +#include #include #include "test_data.hpp" -#include "test_helpers.hpp" using namespace rabitqlib; using namespace rabitq_test; @@ -41,6 +42,26 @@ TEST_F(RotatorTest, DefaultRotatorType) { EXPECT_GE(padded_dim, dim); } +TEST_F(RotatorTest, RejectsPaddedDimensionSmallerThanInput) { + EXPECT_THROW( + (choose_rotator(dim, RotatorType::FhtKacRotator, dim / 2)), + std::invalid_argument + ); + EXPECT_THROW( + (choose_rotator(dim, RotatorType::MatrixRotator, dim / 2)), + std::invalid_argument + ); +} + +TEST_F(RotatorTest, RejectsZeroDimension) { + EXPECT_THROW( + (choose_rotator(0, RotatorType::FhtKacRotator)), std::invalid_argument + ); + EXPECT_THROW( + (choose_rotator(0, RotatorType::MatrixRotator)), std::invalid_argument + ); +} + uint8_t bitreverse8(uint8_t x) { x = (((x & 0x55) << 1) | ((x & 0xAA) >> 1)); x = (((x & 0x33) << 2) | ((x & 0xCC) >> 2)); diff --git a/tests/unit/rabitqlib/utils/space_test.cpp b/tests/unit/rabitqlib/utils/space_test.cpp index 9044ed8..21b0ca8 100644 --- a/tests/unit/rabitqlib/utils/space_test.cpp +++ b/tests/unit/rabitqlib/utils/space_test.cpp @@ -4,12 +4,15 @@ #include #include +#include #include #include #include "rabitqlib/simd/pack_excode_dispatch.hpp" #include "rabitqlib/simd/space_dispatch.hpp" +#include "rabitqlib/simd/warmup_dispatch.hpp" #include "rabitqlib/utils/cpu_features.hpp" +#include "rabitqlib/utils/warmup_space.hpp" using namespace rabitqlib; @@ -21,9 +24,9 @@ TEST(PackBinary, SupportsUnalignedOutput) { } alignas(uint64_t) std::array storage{}; - auto* output = reinterpret_cast(storage.data() + 1); + auto* output = storage.data() + 1; ASSERT_NE(reinterpret_cast(output) % alignof(uint64_t), 0U); - pack_binary(binary_code.data(), output, dim); + pack_binary_to_bytes(binary_code.data(), output, dim); const std::array packed{ load_unaligned_u64(storage.data() + 1), @@ -48,9 +51,9 @@ TEST(MaskIpX0Q, SupportsUnalignedCodes) { } alignas(uint64_t) std::array storage{}; - auto* codes = reinterpret_cast(storage.data() + 1); + auto* codes = storage.data() + 1; ASSERT_NE(reinterpret_cast(codes) % alignof(uint64_t), 0U); - pack_binary(binary_code.data(), codes, dim); + pack_binary_to_bytes(binary_code.data(), codes, dim); if (cpu::has_avx2()) { EXPECT_FLOAT_EQ(simd::mask_ip_x0_q_avx2(query.data(), codes, dim), expected); @@ -61,6 +64,51 @@ TEST(MaskIpX0Q, SupportsUnalignedCodes) { EXPECT_FLOAT_EQ(mask_ip_x0_q(query.data(), codes, dim), expected); } +TEST(WarmupIpX0Q, SupportsUnalignedCodes) { + constexpr float delta = 0.5F; + constexpr float vl = -0.25F; + for (size_t dim : {64UL, 128UL, 192UL, 448UL, 512UL, 576UL}) { + SCOPED_TRACE(dim); + std::vector data_bits(dim); + std::vector query_bits(dim); + size_t data_popcount = 0; + size_t intersection_popcount = 0; + for (size_t i = 0; i < dim; ++i) { + data_bits[i] = (i % 3) == 0; + query_bits[i] = (i % 5) == 0; + data_popcount += data_bits[i] != 0; + intersection_popcount += data_bits[i] != 0 && query_bits[i] != 0; + } + + std::vector storage((dim / 8) + 1); + auto* codes = storage.data() + 1; + ASSERT_NE(reinterpret_cast(codes) % alignof(uint64_t), 0U); + pack_binary_to_bytes(data_bits.data(), codes, dim); + std::vector query(dim / 64); + pack_binary(query_bits.data(), query.data(), dim); + const float expected = delta * static_cast(intersection_popcount) + + vl * static_cast(data_popcount); + + if (cpu::has_avx2()) { + EXPECT_FLOAT_EQ( + simd::warmup_ip_x0_q_512_avx2(codes, query.data(), delta, vl, dim, 1), + expected + ); + } + if (cpu::has_avx512_popcnt()) { + EXPECT_FLOAT_EQ( + simd::warmup_ip_x0_q_512_avx512(codes, query.data(), delta, vl, dim, 1), + expected + ); + } + if (cpu::has_avx2()) { + EXPECT_FLOAT_EQ( + warmup_ip_x0_q_512(codes, query.data(), delta, vl, dim, 1), expected + ); + } + } +} + TEST(Select_IP_Func, returns_stable_function_pointer) { auto ip_func = select_excode_ipfunc(0); ASSERT_NE(ip_func, nullptr);