Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
59eea4c
refactor: add extra meta size
richyreachy Mar 24, 2026
517ce50
feat: turbo distances
richyreachy Mar 24, 2026
51cc10e
refactor: fix int4 ip
richyreachy Mar 25, 2026
12395f6
refactor: add avx2 int4 l2
richyreachy Mar 25, 2026
1ed3209
refactor: add dist funcs
richyreachy Mar 26, 2026
c6f37d2
refactor: add ut for march
richyreachy Mar 26, 2026
573d585
feat: add turbo ut
richyreachy Mar 27, 2026
fdc0f35
feat: add int8/int4 avx2 sse
richyreachy Mar 27, 2026
7be94e0
feat: add dist
richyreachy Mar 30, 2026
4d21dd8
feat: add dist func
richyreachy Mar 31, 2026
42dd299
feat: add scalar dist funcs
richyreachy Mar 31, 2026
04d86ff
feat: add scalar dist funcs
richyreachy Mar 31, 2026
1958a82
feat: add ut
richyreachy Mar 31, 2026
92340b9
feat: add dist funcs
richyreachy Mar 31, 2026
b748222
feat: add dist funcs
richyreachy Mar 31, 2026
4f885b9
feat: add dist funcs
richyreachy Mar 31, 2026
cf017bc
feat: add dist funcs
richyreachy Mar 31, 2026
faa7e64
feat: add fp16 funcs
richyreachy Mar 31, 2026
c073035
feat: add dist funcs
richyreachy Mar 31, 2026
b6baa89
feat: update ut
richyreachy Apr 1, 2026
83b172c
feat: add dist ut
richyreachy Apr 2, 2026
f9fe8ae
feat: add dist funcs
richyreachy Apr 2, 2026
2b23284
feat: add dist funcs
richyreachy Apr 2, 2026
950c7fd
feat: add cosine and euclidean dist func
richyreachy Apr 2, 2026
5a3bec9
feat: merge main
richyreachy Apr 8, 2026
000a199
refactor: change makefile
richyreachy Apr 9, 2026
27ec0f0
refactor: change makefile
richyreachy Apr 9, 2026
08d995e
fix: fix single dist
richyreachy Apr 10, 2026
b4f4bdc
fix: fix single dist
richyreachy Apr 10, 2026
97455f6
fix: avx512fp16 dist func
richyreachy Apr 13, 2026
1f2b66f
feat: support arm
richyreachy Apr 13, 2026
50fc6d7
feat: add armv8
richyreachy Apr 13, 2026
b0bfa89
feat: add armv8
richyreachy Apr 13, 2026
ebd51ef
feat: add armv8
richyreachy Apr 13, 2026
fe8d72a
fix: armv8
richyreachy Apr 13, 2026
f29d6dd
fix: fix typo
richyreachy Apr 13, 2026
53ffc8e
fix: fix dist
richyreachy Apr 13, 2026
85f8cc6
Merge branch 'main' into refactor/turbo
richyreachy Apr 13, 2026
3e45b87
fix: fix dist
richyreachy Apr 13, 2026
e26610a
fix: vnni inner product
richyreachy Apr 13, 2026
b433e6b
fix: fix batch ut
richyreachy Apr 14, 2026
36c4f4c
feat: add batch ut
richyreachy Apr 14, 2026
895cd78
feat: add batch dist
richyreachy Apr 14, 2026
41efb29
fix: fix batch dist
richyreachy Apr 15, 2026
1d02de3
feat: add quantizer
richyreachy Apr 16, 2026
8686780
feat: add quantizer
richyreachy Apr 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/core/framework/index_meta.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ struct IndexMetaFormatHeader {
uint32_t space_id;
uint32_t attachment_offset;
uint32_t attachment_size;
uint8_t reserved_[4092];
uint32_t extra_meta_size;
uint8_t reserved_[4088];
};

static_assert(sizeof(IndexMetaFormatHeader) % 32 == 0,
Expand All @@ -47,6 +48,7 @@ void IndexMeta::serialize(std::string *out) const {
format.dimension = dimension_;
format.unit_size = unit_size_;
format.space_id = space_id_;
format.extra_meta_size = extra_meta_size_;

if (!metric_name_.empty()) {
ailego::Params item;
Expand Down
36 changes: 28 additions & 8 deletions src/core/metric/quantized_integer_metric.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,24 +96,44 @@ class QuantizedIntegerMetric : public IndexMetric {
switch (origin_metric_type_) {
case MetricType::kSquaredEuclidean:
if (meta_.data_type() == IndexMeta::DataType::DT_INT8) {
auto turbo_ret = turbo::get_distance_func(
turbo::MetricType::kSquaredEuclidean, turbo::DataType::kInt8,
turbo::QuantizeType::kDefault);
auto turbo_ret =
turbo::get_distance_func(turbo::MetricType::kSquaredEuclidean,
turbo::DataType::kInt8, quantize_type_);
if (turbo_ret && m == 1 && n == 1) {
return turbo_ret;
}
return DistanceMatrixCompute<SquaredEuclidean, int8_t>(m, n);
}
if (meta_.data_type() == IndexMeta::DataType::DT_INT4) {
auto turbo_ret =
turbo::get_distance_func(turbo::MetricType::kSquaredEuclidean,
turbo::DataType::kInt4, quantize_type_);
if (turbo_ret && m == 1 && n == 1) {
return turbo_ret;
}

return DistanceMatrixCompute<SquaredEuclidean, uint8_t>(m, n);
}
break;

case MetricType::kInnerProduct:
if (meta_.data_type() == IndexMeta::DataType::DT_INT8) {
auto turbo_ret =
turbo::get_distance_func(turbo::MetricType::kInnerProduct,
turbo::DataType::kInt8, quantize_type_);
if (turbo_ret && m == 1 && n == 1) {
return turbo_ret;
}
return DistanceMatrixCompute<MinusInnerProduct, int8_t>(m, n);
}

if (meta_.data_type() == IndexMeta::DataType::DT_INT4) {
auto turbo_ret =
turbo::get_distance_func(turbo::MetricType::kInnerProduct,
turbo::DataType::kInt4, quantize_type_);
if (turbo_ret && m == 1 && n == 1) {
return turbo_ret;
}
return DistanceMatrixCompute<MinusInnerProduct, uint8_t>(m, n);
}
break;
Expand All @@ -137,9 +157,9 @@ class QuantizedIntegerMetric : public IndexMetric {
break;
case MetricType::kCosine:
if (meta_.data_type() == IndexMeta::DataType::DT_INT8) {
auto turbo_ret = turbo::get_distance_func(
turbo::MetricType::kCosine, turbo::DataType::kInt8,
turbo::QuantizeType::kDefault);
auto turbo_ret =
turbo::get_distance_func(turbo::MetricType::kCosine,
turbo::DataType::kInt8, quantize_type_);
if (turbo_ret) {
return turbo_ret;
}
Expand All @@ -160,7 +180,7 @@ class QuantizedIntegerMetric : public IndexMetric {
if (meta_.data_type() == IndexMeta::DataType::DT_INT8) {
auto turbo_ret = turbo::get_batch_distance_func(
turbo::MetricType::kSquaredEuclidean, turbo::DataType::kInt8,
turbo::QuantizeType::kDefault);
quantize_type_);
if (turbo_ret) {
return turbo_ret;
}
Expand Down Expand Up @@ -215,7 +235,7 @@ class QuantizedIntegerMetric : public IndexMetric {
if (meta_.data_type() == IndexMeta::DataType::DT_INT8) {
auto turbo_ret = turbo::get_batch_distance_func(
turbo::MetricType::kCosine, turbo::DataType::kInt8,
turbo::QuantizeType::kDefault);
quantize_type_);
if (turbo_ret) {
return turbo_ret;
}
Expand Down
4 changes: 4 additions & 0 deletions src/include/zvec/core/framework/index_meta.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class IndexMeta {
DT_BINARY64 = 8,
};


/*! Major Orders
*/
enum MajorOrder {
Expand Down Expand Up @@ -586,6 +587,7 @@ class IndexMeta {
uint32_t dimension_{0};
uint32_t unit_size_{0};
uint32_t element_size_{0};
uint32_t extra_meta_size_{0};
uint64_t space_id_{0};
uint32_t metric_revision_{0};
uint32_t converter_revision_{0};
Expand Down Expand Up @@ -708,6 +710,8 @@ class IndexQueryMeta {
uint32_t dimension_{0};
uint32_t unit_size_{0};
uint32_t element_size_{0};
uint32_t extra_meta_size_{0};
uint32_t quantize_type_{0};
};

} // namespace core
Expand Down
3 changes: 3 additions & 0 deletions src/include/zvec/core/framework/index_metric.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ struct IndexMetric : public IndexModule {
virtual DistanceBatchQueryPreprocessFunc get_query_preprocess_func() const {
return nullptr;
}

private:
int quantize_type_{0};
};

} // namespace core
Expand Down
37 changes: 30 additions & 7 deletions src/include/zvec/turbo/turbo.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,51 @@ using QueryPreprocessFunc =
enum class MetricType {
kSquaredEuclidean,
kCosine,
kInnerProduct,
kMipsSquaredEuclidean,
kUnknown,
};

enum class DataType {
kInt4,
kInt8,
kFp16,
kFp32,
kUnknown,
};

enum class QuantizeType {
kDefault,
kRecordInt8,
kRecordInt4,
kInt8,
kInt4,
kFp16,
kPQ,
kRabit
};

enum class CpuArchType {
kAuto,
kScalar,
kSSE,
kAVX,
kAVX2,
kAVX512,
kAVX512VNNI,
kAVX512FP16
};

DistanceFunc get_distance_func(MetricType metric_type, DataType data_type,
QuantizeType quantize_type);
QuantizeType quantize_type,
CpuArchType cpu_arch_type = CpuArchType::kAuto);

BatchDistanceFunc get_batch_distance_func(MetricType metric_type,
DataType data_type,
QuantizeType quantize_type);
BatchDistanceFunc get_batch_distance_func(
MetricType metric_type, DataType data_type, QuantizeType quantize_type,
CpuArchType cpu_arch_type = CpuArchType::kAuto);

QueryPreprocessFunc get_query_preprocess_func(MetricType metric_type,
DataType data_type,
QuantizeType quantize_type);
QueryPreprocessFunc get_query_preprocess_func(
MetricType metric_type, DataType data_type, QuantizeType quantize_type,
CpuArchType cpu_arch_type = CpuArchType::kAuto);

} // namespace zvec::turbo
63 changes: 58 additions & 5 deletions src/turbo/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,71 @@ endif()

file(GLOB_RECURSE ALL_SRCS *.cc *.c *.h)

# Set per-file compile flags for AVX512-VNNI sources.
# set_source_files_properties is directory-scoped, so it must be called in the
# same directory that adds the sources to a target (i.e. here, not in a
# subdirectory).
if(NOT ANDROID AND AUTO_DETECT_ARCH)
if (HOST_ARCH MATCHES "^(x86|x64)$")
file(GLOB_RECURSE AVX512_VNNI_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/avx512_vnni/*.cc)
file(GLOB_RECURSE AVX512_AVX512FP16_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/avx512_fp16/*.cc
${CMAKE_CURRENT_SOURCE_DIR}/avx512_fp16/*.c)
set_source_files_properties(
${AVX512_AVX512FP16_SRCS}
PROPERTIES
COMPILE_FLAGS "${TURBO_MARCH_FLAG_AVX512FP16}"
)

# Set per-file compile flags for AVX512-VNNI sources.
# set_source_files_properties is directory-scoped, so it must be called in the
# same directory that adds the sources to a target (i.e. here, not in a
# subdirectory).
file(GLOB_RECURSE AVX512_VNNI_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/avx512_vnni/*.cc
${CMAKE_CURRENT_SOURCE_DIR}/avx512_vnni/*.c)
set_source_files_properties(
${AVX512_VNNI_SRCS}
PROPERTIES
COMPILE_FLAGS "${TURBO_MARCH_FLAG_AVX512}"
)

file(GLOB_RECURSE AVX512_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/avx512/*.cc
${CMAKE_CURRENT_SOURCE_DIR}/avx512/*.c)
set_source_files_properties(
${AVX512_SRCS}
PROPERTIES
COMPILE_FLAGS "${TURBO_MARCH_FLAG_AVX512}"
)

file(GLOB_RECURSE AVX2_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/avx2/*.cc
${CMAKE_CURRENT_SOURCE_DIR}/avx2/*.c
${CMAKE_CURRENT_SOURCE_DIR}/avx/*.cc
${CMAKE_CURRENT_SOURCE_DIR}/avx/*.c)
set_source_files_properties(
${AVX2_SRCS}
PROPERTIES
COMPILE_FLAGS "${TURBO_MARCH_FLAG_AVX2}"
)

file(GLOB_RECURSE SSE_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/sse/*.cc
${CMAKE_CURRENT_SOURCE_DIR}/sse/*.c)
set_source_files_properties(
${SSE_SRCS}
PROPERTIES
COMPILE_FLAGS "${TURBO_MARCH_FLAG_SSE}"
)
elseif (HOST_ARCH MATCHES "^(arm|arm64)$")
set(TURBO_MARCH_FLAG_NEON "-march=armv8-a")

file(GLOB_RECURSE NEON_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/armv8/*.cc
${CMAKE_CURRENT_SOURCE_DIR}/armv8/*.c
)

set_source_files_properties(
${NEON_SRCS}
PROPERTIES
COMPILE_FLAGS "${TURBO_MARCH_FLAG_NEON}"
)
endif()
endif()

Expand Down
62 changes: 62 additions & 0 deletions src/turbo/armv8/float32/cosine.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2025-present the zvec project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "armv8/float32/cosine.h"
#include "armv8/float32/inner_product.h"
#include "armv8/float32/inner_product_common.h"

namespace zvec::turbo::armv8 {

void cosine_fp32_distance(const void *a, const void *b, size_t dim,
size_t extra_size, float *distance) {
#if defined(__ARM_NEON)
constexpr size_t extra_dim = 2;
size_t original_dim = dim - extra_dim;

float ip;
internal::inner_product_fp32_armv8(a, b, original_dim, &ip);

*distance = 1 - ip;
#else
(void)a;
(void)b;
(void)dim;
(void)distance;
#endif // __ARM_NEON
}

void cosine_fp32_batch_distance(const void *const *vectors, const void *query,
size_t n, size_t dim, float *distances) {
#if defined(__ARM_NEON)
const int original_dim = dim - 1;
if (original_dim <= 0) {
return;
}

internal::inner_product_fp32_batch_armv8(vectors, query, n, original_dim,
distances);

for (int i = 0; i < n; ++i) {
distances[i] = 1 - distances[i];
}
#else
(void)vectors;
(void)query;
(void)n;
(void)dim;
(void)distances;
#endif //__ARM_NEON
}

} // namespace zvec::turbo::armv8
30 changes: 30 additions & 0 deletions src/turbo/armv8/float32/cosine.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2025-present the zvec project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <cstddef>

namespace zvec::turbo::armv8 {

// Compute cosine distance (negative inner product after normalization) between
// a single quantized FP32 vector pair.
void cosine_fp32_distance(const void *a, const void *b, size_t dim,
float *distance);

// Batch version of cosine_fp32_distance.
void cosine_fp32_batch_distance(const void *const *vectors, const void *query,
size_t n, size_t dim, float *distances);

} // namespace zvec::turbo::armv8
Loading