Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion examples/c++/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ set(zvec_ailego_deps
)

set(zvec_core_deps
# empty
zvec_turbo
)

set(zvec_db_deps
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ git_version(ZVEC_VERSION ${CMAKE_CURRENT_SOURCE_DIR})
cc_directory(ailego)
cc_directory(core)
cc_directory(db)
cc_directory(turbo)
if(BUILD_PYTHON_BINDINGS)
cc_directory(binding)
endif()
2 changes: 1 addition & 1 deletion src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ file(GLOB_RECURSE ALL_CORE_SRCS *.cc *.c *.h)
cc_library(
NAME zvec_core STATIC STRICT PACKED
SRCS ${ALL_CORE_SRCS}
LIBS zvec_ailego sparsehash magic_enum
LIBS zvec_ailego zvec_turbo sparsehash magic_enum
INCS . ${PROJECT_ROOT_DIR}/src/core
VERSION "${GIT_SRCS_VER}"
)
2 changes: 1 addition & 1 deletion src/core/metric/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ cc_library(
NAME core_metric
STATIC SHARED STRICT ALWAYS_LINK
SRCS *.cc
LIBS zvec_ailego core_framework
LIBS zvec_ailego zvec_turbo core_framework
INCS . ${PROJECT_ROOT_DIR}/src/core
VERSION "${PROXIMA_ZVEC_VERSION}"
)
19 changes: 19 additions & 0 deletions src/core/metric/quantized_integer_metric.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <ailego/math_batch/distance_batch.h>
#include <zvec/core/framework/index_error.h>
#include <zvec/core/framework/index_factory.h>
#include <zvec/turbo/turbo.h>
#include "metric_params.h"
#include "quantized_integer_metric_batch.h"
#include "quantized_integer_metric_matrix.h"
Expand Down Expand Up @@ -95,6 +96,12 @@ 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);
if (turbo_ret) {
return turbo_ret;
}
return DistanceMatrixCompute<SquaredEuclidean, int8_t>(m, n);
Comment on lines +99 to 105
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0 Turbo 1×1 function returned for all m × n matrix cases

turbo::DistanceFunc has the same ABI as MatrixDistance — both are std::function<void(const void*, const void*, size_t, float*)> — but their calling conventions differ. For m = 1, n = 1 the pointers are treated as single vectors. For m = M, n = N > 1, callers interpret the first pointer as M tightly-packed vectors and the output as an M × N float matrix. The turbo function only ever computes a single inner product, so calling it in place of an 8 × 4 matrix kernel writes one float instead of 32, leaving the rest uninitialised and corrupting the caller's output array.

The turbo path should be limited to the 1×1 case:

Suggested change
auto turbo_ret = turbo::get_distance_func(
turbo::MetricType::kSquaredEuclidean, turbo::DataType::kInt8,
turbo::QuantizeType::kDefault);
if (turbo_ret) {
return turbo_ret;
}
return DistanceMatrixCompute<SquaredEuclidean, int8_t>(m, n);
if (m == 1 && n == 1) {
auto turbo_ret = turbo::get_distance_func(
turbo::MetricType::kSquaredEuclidean, turbo::DataType::kInt8,
turbo::QuantizeType::kDefault);
if (turbo_ret) {
return turbo_ret;
}
}
return DistanceMatrixCompute<SquaredEuclidean, int8_t>(m, n);

}
if (meta_.data_type() == IndexMeta::DataType::DT_INT4) {
Expand Down Expand Up @@ -146,6 +153,12 @@ class QuantizedIntegerMetric : public IndexMetric {
switch (origin_metric_type_) {
case MetricType::kSquaredEuclidean:
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);
if (turbo_ret) {
return turbo_ret;
}
return reinterpret_cast<IndexMetric::MatrixBatchDistanceHandle>(
BaseDistanceBatchWithScoreUnquantized<SquaredEuclidean, int8_t,
12, 2>::ComputeBatch);
Expand Down Expand Up @@ -268,6 +281,12 @@ class QuantizedIntegerMetric : public IndexMetric {
int8_t, 1, 1>::GetQueryPreprocessFunc();
} else if (origin_metric_type_ == MetricType::kSquaredEuclidean &&
meta_.data_type() == IndexMeta::DataType::DT_INT8) {
auto turbo_ret = turbo::get_query_preprocess_func(
turbo::MetricType::kSquaredEuclidean, turbo::DataType::kInt8,
turbo::QuantizeType::kDefault);
if (turbo_ret) {
return turbo_ret;
}
return SquaredEuclideanDistanceBatchWithScoreUnquantized<
int8_t, 1, 1>::GetQueryPreprocessFunc();
}
Expand Down
53 changes: 53 additions & 0 deletions src/include/zvec/turbo/turbo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// 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 <functional>
#include <zvec/ailego/math_batch/utils.h>

namespace zvec::turbo {

using DistanceFunc =
std::function<void(const void *m, const void *q, size_t dim, float *out)>;
using BatchDistanceFunc = std::function<void(
const void **m, const void *q, size_t num, size_t dim, float *out)>;
using QueryPreprocessFunc =
zvec::ailego::DistanceBatch::DistanceBatchQueryPreprocessFunc;

enum class MetricType {
kSquaredEuclidean,
kUnknown,
};

enum class DataType {
kInt8,
kUnknown,
};

enum class QuantizeType {
kDefault,
};

DistanceFunc get_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);

QueryPreprocessFunc get_query_preprocess_func(MetricType metric_type,
DataType data_type,
QuantizeType quantize_type);

} // namespace zvec::turbo
25 changes: 25 additions & 0 deletions src/turbo/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
include(${PROJECT_ROOT_DIR}/cmake/bazel.cmake)
include(${PROJECT_ROOT_DIR}/cmake/option.cmake)

if(NOT ANDROID AND AUTO_DETECT_ARCH)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|i686|i386|x64")
setup_compiler_march_for_x86(TURBO_MARCH_FLAG_SSE TURBO_MARCH_FLAG_AVX2 TURBO_MARCH_FLAG_AVX512)
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/euclidean/avx512_impl.cc
PROPERTIES
COMPILE_FLAGS "${TURBO_MARCH_FLAG_AVX512}"
)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|ARM64")
# ARM64 architecture - no special march flags needed for now
# NEON implementations can be added here if needed
message(STATUS "turbo: ARM64 detected, skipping x86-specific optimizations")
endif()
endif()

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

cc_library(
NAME zvec_turbo STATIC STRICT PACKED
SRCS ${ALL_SRCS}
INCS ${PROJECT_ROOT_DIR}/src/include/zvec
)
Loading
Loading