From f5cb4c4946a5b03cea8d74e0761583a592a9a354 Mon Sep 17 00:00:00 2001 From: Ocean Date: Mon, 16 Feb 2026 22:40:09 +0100 Subject: [PATCH 1/5] fix(cmake): use -march=native instead of probing highest compiler-supported arch The auto-detection in _detect_x86_best() iterated from the highest microarchitecture (graniterapids) down and picked the first one the *compiler* accepted. Since compilers accept all -march= flags regardless of the host CPU, this would emit e.g. AVX-512BW instructions on machines that only support AVX2, causing SIGILL at runtime. Replace with -march=native which targets the actual build machine's ISA. Fixes #128 Fixes #92 --- cmake/option.cmake | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/cmake/option.cmake b/cmake/option.cmake index ca74cf05..151b204e 100644 --- a/cmake/option.cmake +++ b/cmake/option.cmake @@ -89,23 +89,20 @@ function(_detect_armv8_best) endfunction() function(_detect_x86_best) - set(_x86_flags - "graniterapids" "emeraldrapids" "sapphirerapids" - "skylake-avx512" "skylake" - "broadwell" "haswell" "sandybridge" "nehalem" - "znver3" "znver2" "znver1" - ) - foreach(_arch IN LISTS _x86_flags) - check_c_compiler_flag("-march=${_arch}" _COMP_SUPP_${_arch}) - if(_COMP_SUPP_${_arch}) - _AppendFlags(CMAKE_C_FLAGS "-march=${_arch}") - _AppendFlags(CMAKE_CXX_FLAGS "-march=${_arch}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" PARENT_SCOPE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE) - return() - endif() - endforeach() - message(WARNING "No known x86 microarchitecture flag supported; falling back to generic.") + # Use -march=native to target the actual build machine's CPU. + # The previous approach iterated from highest to lowest arch and checked + # whether the *compiler* accepted the flag — but the compiler will accept + # e.g. -march=skylake-avx512 on any machine, which then emits AVX-512 + # instructions that crash on CPUs without those extensions (see #128, #92). + check_c_compiler_flag("-march=native" _COMP_SUPP_NATIVE) + if(_COMP_SUPP_NATIVE) + _AppendFlags(CMAKE_C_FLAGS "-march=native") + _AppendFlags(CMAKE_CXX_FLAGS "-march=native") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE) + return() + endif() + message(WARNING "Compiler does not support -march=native; falling back to generic x86-64.") endfunction() if(MSVC) From 10a9197cd8f216cd2b141a0a8e3a1ba7ff3e863b Mon Sep 17 00:00:00 2001 From: Ocean Date: Mon, 16 Feb 2026 22:40:18 +0100 Subject: [PATCH 2/5] fix: rename misspelled 'adjuct' to 'adjust' in HNSW context methods The method check_need_adjuct_ctx() was consistently misspelled across both dense and sparse HNSW implementations. Renamed to check_need_adjust_ctx() for correctness. --- src/core/algorithm/hnsw/hnsw_context.cc | 2 +- src/core/algorithm/hnsw/hnsw_context.h | 6 +++--- src/core/algorithm/hnsw/hnsw_streamer.cc | 8 ++++---- src/core/algorithm/hnsw_sparse/hnsw_sparse_context.cc | 2 +- src/core/algorithm/hnsw_sparse/hnsw_sparse_context.h | 6 +++--- src/core/algorithm/hnsw_sparse/hnsw_sparse_streamer.cc | 6 +++--- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/core/algorithm/hnsw/hnsw_context.cc b/src/core/algorithm/hnsw/hnsw_context.cc index b930e418..0ff764c2 100644 --- a/src/core/algorithm/hnsw/hnsw_context.cc +++ b/src/core/algorithm/hnsw/hnsw_context.cc @@ -77,7 +77,7 @@ int HnswContext::init(ContextType type) { update_heap_.limit(entity_->l0_neighbor_cnt() + 1); candidates_.limit(max_scan_num_); - check_need_adjuct_ctx(); + check_need_adjust_ctx(); break; default: diff --git a/src/core/algorithm/hnsw/hnsw_context.h b/src/core/algorithm/hnsw/hnsw_context.h index 22bcfaad..695e52da 100644 --- a/src/core/algorithm/hnsw/hnsw_context.h +++ b/src/core/algorithm/hnsw/hnsw_context.h @@ -361,8 +361,8 @@ class HnswContext : public IndexContext { return level_topks_[level]; } - inline void check_need_adjuct_ctx(void) { - check_need_adjuct_ctx(entity_->doc_cnt()); + inline void check_need_adjust_ctx(void) { + check_need_adjust_ctx(entity_->doc_cnt()); } inline size_t compute_reserve_cnt(uint32_t cur_doc) const { @@ -375,7 +375,7 @@ class HnswContext : public IndexContext { } //! candidates heap and visitfilter need to resize as doc cnt growing up - inline void check_need_adjuct_ctx(uint32_t doc_cnt) { + inline void check_need_adjust_ctx(uint32_t doc_cnt) { if (ailego_unlikely(doc_cnt + kTriggerReserveCnt > reserve_max_doc_cnt_)) { while (doc_cnt + kTriggerReserveCnt > reserve_max_doc_cnt_) { reserve_max_doc_cnt_ = diff --git a/src/core/algorithm/hnsw/hnsw_streamer.cc b/src/core/algorithm/hnsw/hnsw_streamer.cc index 5804c7d0..e36b31af 100644 --- a/src/core/algorithm/hnsw/hnsw_streamer.cc +++ b/src/core/algorithm/hnsw/hnsw_streamer.cc @@ -391,7 +391,7 @@ IndexStreamer::Context::Pointer HnswStreamer::create_context(void) const { LOG_DEBUG("HnswStreamer doc_count[%zu] estimate[%zu]", (size_t)entity_.doc_cnt(), (size_t)estimate_doc_count); } - ctx->check_need_adjuct_ctx(std::max(entity_.doc_cnt(), estimate_doc_count)); + ctx->check_need_adjust_ctx(std::max(entity_.doc_cnt(), estimate_doc_count)); return Context::Pointer(ctx); } @@ -466,7 +466,7 @@ int HnswStreamer::add_with_id_impl(uint32_t id, const void *query, ctx->clear(); ctx->update_dist_caculator_distance(add_distance_, add_batch_distance_); ctx->reset_query(query); - ctx->check_need_adjuct_ctx(entity_.doc_cnt()); + ctx->check_need_adjust_ctx(entity_.doc_cnt()); if (metric_->support_train()) { const std::lock_guard lk(mutex_); @@ -546,7 +546,7 @@ int HnswStreamer::add_impl(uint64_t pkey, const void *query, ctx->clear(); ctx->update_dist_caculator_distance(add_distance_, add_batch_distance_); ctx->reset_query(query); - ctx->check_need_adjuct_ctx(entity_.doc_cnt()); + ctx->check_need_adjust_ctx(entity_.doc_cnt()); if (metric_->support_train()) { const std::lock_guard lk(mutex_); @@ -618,7 +618,7 @@ int HnswStreamer::search_impl(const void *query, const IndexQueryMeta &qmeta, ctx->clear(); ctx->update_dist_caculator_distance(search_distance_, search_batch_distance_); ctx->resize_results(count); - ctx->check_need_adjuct_ctx(entity_.doc_cnt()); + ctx->check_need_adjust_ctx(entity_.doc_cnt()); for (size_t q = 0; q < count; ++q) { ctx->reset_query(query); ret = alg_->search(ctx); diff --git a/src/core/algorithm/hnsw_sparse/hnsw_sparse_context.cc b/src/core/algorithm/hnsw_sparse/hnsw_sparse_context.cc index de3dfdd9..a8ec1577 100644 --- a/src/core/algorithm/hnsw_sparse/hnsw_sparse_context.cc +++ b/src/core/algorithm/hnsw_sparse/hnsw_sparse_context.cc @@ -71,7 +71,7 @@ int HnswSparseContext::init(ContextType type) { update_heap_.limit(entity_->l0_neighbor_cnt() + 1); candidates_.limit(max_scan_num_); - check_need_adjuct_ctx(); + check_need_adjust_ctx(); break; default: diff --git a/src/core/algorithm/hnsw_sparse/hnsw_sparse_context.h b/src/core/algorithm/hnsw_sparse/hnsw_sparse_context.h index d8ef2fe7..fe755279 100644 --- a/src/core/algorithm/hnsw_sparse/hnsw_sparse_context.h +++ b/src/core/algorithm/hnsw_sparse/hnsw_sparse_context.h @@ -357,8 +357,8 @@ class HnswSparseContext : public IndexContext { return level_topks_[level]; } - inline void check_need_adjuct_ctx(void) { - check_need_adjuct_ctx(entity_->doc_cnt()); + inline void check_need_adjust_ctx(void) { + check_need_adjust_ctx(entity_->doc_cnt()); } inline size_t compute_reserve_cnt(uint32_t cur_doc) const { @@ -371,7 +371,7 @@ class HnswSparseContext : public IndexContext { } //! candidates heap and visitfilter need to resize as doc cnt growing up - inline void check_need_adjuct_ctx(uint32_t doc_cnt) { + inline void check_need_adjust_ctx(uint32_t doc_cnt) { if (ailego_unlikely(doc_cnt + kTriggerReserveCnt > reserve_max_doc_cnt_)) { while (doc_cnt + kTriggerReserveCnt > reserve_max_doc_cnt_) { reserve_max_doc_cnt_ = diff --git a/src/core/algorithm/hnsw_sparse/hnsw_sparse_streamer.cc b/src/core/algorithm/hnsw_sparse/hnsw_sparse_streamer.cc index f51ebb5e..5c732956 100644 --- a/src/core/algorithm/hnsw_sparse/hnsw_sparse_streamer.cc +++ b/src/core/algorithm/hnsw_sparse/hnsw_sparse_streamer.cc @@ -485,7 +485,7 @@ int HnswSparseStreamer::add_with_id_impl(uint32_t id, sparse_query_buffer); ctx->reset_query(sparse_query_buffer.data()); - ctx->check_need_adjuct_ctx(entity_.doc_cnt()); + ctx->check_need_adjust_ctx(entity_.doc_cnt()); level_t level = alg_->get_random_level(); ret = @@ -570,7 +570,7 @@ int HnswSparseStreamer::add_impl(uint64_t pkey, const uint32_t sparse_count, sparse_query_buffer); ctx->reset_query(sparse_query_buffer.data()); - ctx->check_need_adjuct_ctx(entity_.doc_cnt()); + ctx->check_need_adjust_ctx(entity_.doc_cnt()); level_t level = alg_->get_random_level(); node_id_t id; @@ -637,7 +637,7 @@ int HnswSparseStreamer::search_impl( ctx->clear(); ctx->update_dist_caculator_distance(search_distance_); ctx->resize_results(count); - ctx->check_need_adjuct_ctx(entity_.doc_cnt()); + ctx->check_need_adjust_ctx(entity_.doc_cnt()); const uint32_t *sparse_indices_tmp = sparse_indices; const void *sparse_query_tmp = sparse_query; From 27f3243c950bea3348c342f04d0912f69ec81def Mon Sep 17 00:00:00 2001 From: Ocean Date: Mon, 16 Feb 2026 22:40:28 +0100 Subject: [PATCH 3/5] fix: correct typos across codebase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 'wiht' → 'with' in index_reducer.h, index.cc, mixed_streamer_reducer - 'spase' → 'sparse' in hnsw_builder_entity.h, hnsw_sparse_builder_entity.h - 'seperate' → 'separate' in vector_column_indexer.h - Fix extra space in README.md HTML align attribute --- README.md | 2 +- src/core/algorithm/hnsw/hnsw_builder_entity.h | 2 +- src/core/algorithm/hnsw_sparse/hnsw_sparse_builder_entity.h | 2 +- src/core/interface/index.cc | 2 +- src/core/mixed_reducer/mixed_streamer_reducer.cc | 2 +- src/core/mixed_reducer/mixed_streamer_reducer.h | 2 +- src/db/index/column/vector_column/vector_column_indexer.h | 2 +- src/include/zvec/core/framework/index_reducer.h | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index cd9f6866..e3fa5352 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -
+
zvec logo diff --git a/src/core/algorithm/hnsw/hnsw_builder_entity.h b/src/core/algorithm/hnsw/hnsw_builder_entity.h index 1708e338..6f3e55ef 100644 --- a/src/core/algorithm/hnsw/hnsw_builder_entity.h +++ b/src/core/algorithm/hnsw/hnsw_builder_entity.h @@ -123,7 +123,7 @@ class HnswBuilderEntity : public HnswEntity { std::string neighbors_buffer_{}; // level 0 neighbors buffer std::string upper_neighbors_buffer_{}; // upper layer neighbors buffer - std::string sparse_data_buffer_{}; // aligned spase data buffer + std::string sparse_data_buffer_{}; // aligned sparse data buffer size_t sparse_data_offset_{0}; // // upper layer offset + level in upper_neighbors_buffer_ diff --git a/src/core/algorithm/hnsw_sparse/hnsw_sparse_builder_entity.h b/src/core/algorithm/hnsw_sparse/hnsw_sparse_builder_entity.h index de35fae7..51ffacf9 100644 --- a/src/core/algorithm/hnsw_sparse/hnsw_sparse_builder_entity.h +++ b/src/core/algorithm/hnsw_sparse/hnsw_sparse_builder_entity.h @@ -146,7 +146,7 @@ class HnswSparseBuilderEntity : public HnswSparseEntity { std::string neighbors_buffer_{}; // level 0 neighbors buffer std::string upper_neighbors_buffer_{}; // upper layer neighbors buffer - std::string sparse_data_buffer_{}; // aligned spase data buffer + std::string sparse_data_buffer_{}; // aligned sparse data buffer size_t sparse_data_offset_{0}; // // upper layer offset + level in upper_neighbors_buffer_ diff --git a/src/core/interface/index.cc b/src/core/interface/index.cc index 038f67d4..3c4eff16 100644 --- a/src/core/interface/index.cc +++ b/src/core/interface/index.cc @@ -769,7 +769,7 @@ int Index::Merge(const std::vector &indexes, LOG_ERROR("Failed to init reducer"); return core::IndexError_Runtime; } - if (reducer->set_target_streamer_wiht_info(builder_, streamer_, converter_, + if (reducer->set_target_streamer_with_info(builder_, streamer_, converter_, reformer_, input_vector_meta_) != 0) { LOG_ERROR("Failed to set target streamer"); diff --git a/src/core/mixed_reducer/mixed_streamer_reducer.cc b/src/core/mixed_reducer/mixed_streamer_reducer.cc index b5e241bb..30155c84 100644 --- a/src/core/mixed_reducer/mixed_streamer_reducer.cc +++ b/src/core/mixed_reducer/mixed_streamer_reducer.cc @@ -55,7 +55,7 @@ int MixedStreamerReducer::cleanup(void) { return 0; } -int MixedStreamerReducer::set_target_streamer_wiht_info( +int MixedStreamerReducer::set_target_streamer_with_info( const IndexBuilder::Pointer builder, const IndexStreamer::Pointer streamer, const IndexConverter::Pointer converter, const IndexReformer::Pointer reformer, diff --git a/src/core/mixed_reducer/mixed_streamer_reducer.h b/src/core/mixed_reducer/mixed_streamer_reducer.h index ec4c6240..8080894e 100644 --- a/src/core/mixed_reducer/mixed_streamer_reducer.h +++ b/src/core/mixed_reducer/mixed_streamer_reducer.h @@ -45,7 +45,7 @@ class MixedStreamerReducer : public IndexStreamerReducer { int dump(const IndexDumper::Pointer &dumper) override; public: // StreamerReducer's unique methods - int set_target_streamer_wiht_info( + int set_target_streamer_with_info( const IndexBuilder::Pointer builder, const IndexStreamer::Pointer streamer, const IndexConverter::Pointer converter, diff --git a/src/db/index/column/vector_column/vector_column_indexer.h b/src/db/index/column/vector_column/vector_column_indexer.h index 80766e1d..9a59daaf 100644 --- a/src/db/index/column/vector_column/vector_column_indexer.h +++ b/src/db/index/column/vector_column/vector_column_indexer.h @@ -123,7 +123,7 @@ class VectorColumnIndexer { std::string engine_name_ = "proxima"; bool is_sparse_{false}; // TODO: eliminate the dynamic flag and make it - // static/template/seperate class + // static/template/separate class }; diff --git a/src/include/zvec/core/framework/index_reducer.h b/src/include/zvec/core/framework/index_reducer.h index 911a0e10..fa605834 100644 --- a/src/include/zvec/core/framework/index_reducer.h +++ b/src/include/zvec/core/framework/index_reducer.h @@ -213,7 +213,7 @@ class IndexStreamerReducer : public IndexReducerBase { //! Index Reducer Pointer typedef std::shared_ptr Pointer; - virtual int set_target_streamer_wiht_info( + virtual int set_target_streamer_with_info( const IndexBuilder::Pointer builder, const IndexStreamer::Pointer streamer, const IndexConverter::Pointer converter, From db668fc095641fc6985210d7d71bb3bcfdf03dbb Mon Sep 17 00:00:00 2001 From: Ocean Date: Mon, 16 Feb 2026 22:40:40 +0100 Subject: [PATCH 4/5] fix: improve error message for cosine metric with unsupported data types When using cosine metric without a quantizer on INT8 data, the error message was a bare 'Unsupported data type: ' with no detail. Now it explains that cosine without quantizer only supports FP32/FP16 and suggests using QuantizerType::kInt8 as a workaround. Related to #78 --- src/core/interface/index.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/core/interface/index.cc b/src/core/interface/index.cc index 3c4eff16..c1b8e14e 100644 --- a/src/core/interface/index.cc +++ b/src/core/interface/index.cc @@ -130,7 +130,10 @@ int Index::CreateAndInitConverterReformer(const QuantizerParam ¶m, } else if (index_param.data_type == DataType::DT_FP32) { converter_name = "CosineNormalizeConverter"; } else { - LOG_ERROR("Unsupported data type: "); + LOG_ERROR( + "Cosine metric without quantizer only supports FP32 and FP16 " + "data types. For INT8 data, use a quantizer " + "(e.g. QuantizerType::kInt8)."); return core::IndexError_Unsupported; } break; From c5e18e39ba56c466ff7a38097ffce1c44b59b250 Mon Sep 17 00:00:00 2001 From: Ocean Date: Mon, 16 Feb 2026 22:40:51 +0100 Subject: [PATCH 5/5] fix: fix full-width exclamation mark in comments and 'Orignal' typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace '!' (U+FF01) with '!' in cpu_features.h/.cc comments - Fix 'Orignal' → 'Original' in cosine_converter.cc error message --- src/ailego/internal/cpu_features.cc | 2 +- src/ailego/internal/cpu_features.h | 4 ++-- src/core/quantizer/cosine_converter.cc | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ailego/internal/cpu_features.cc b/src/ailego/internal/cpu_features.cc index 4bf139ae..d1ca327d 100644 --- a/src/ailego/internal/cpu_features.cc +++ b/src/ailego/internal/cpu_features.cc @@ -327,7 +327,7 @@ bool CpuFeatures::VMX(void) { return !!(flags_.L1_ECX & (1u << 5)); } -// !Running on a hypervisor +//! Running on a hypervisor bool CpuFeatures::HYPERVISOR(void) { return !!(flags_.L1_ECX & (1u << 31)); } diff --git a/src/ailego/internal/cpu_features.h b/src/ailego/internal/cpu_features.h index 3db1dee2..9454ee9a 100644 --- a/src/ailego/internal/cpu_features.h +++ b/src/ailego/internal/cpu_features.h @@ -179,7 +179,7 @@ class CpuFeatures { //! Hardware virtualization static bool VMX(void); - // !Running on a hypervisor + //! Running on a hypervisor static bool HYPERVISOR(void); //! Intrinsics of compiling @@ -359,7 +359,7 @@ class CpuFeatures { //! Hardware virtualization bool VMX = CpuFeatures::VMX(); - // !Running on a hypervisor + //! Running on a hypervisor bool HYPERVISOR = CpuFeatures::HYPERVISOR(); }; static StaticFlags static_flags_; diff --git a/src/core/quantizer/cosine_converter.cc b/src/core/quantizer/cosine_converter.cc index e8deaca8..b0d61740 100644 --- a/src/core/quantizer/cosine_converter.cc +++ b/src/core/quantizer/cosine_converter.cc @@ -254,7 +254,7 @@ class CosineConverter : public IndexConverter { IndexMeta::DataType type = meta_.data_type(); if (type != original_type_) { - LOG_ERROR("Orignal Type Not Matched: (%d, %d)", type, original_type_); + LOG_ERROR("Original Type Not Matched: (%d, %d)", type, original_type_); return IndexError_Mismatch; }