fix: [2.4] [Cherry-pick] dynamically resolve whether SVE is available for bitset (#32139)

Issue: https://github.com/milvus-io/milvus/issues/32129
pr: #32137 
This PR adds a dynamic SVE detection for ARM CPU families for the bitset
code.
Also, allows the code to be compiled if the compiler does not support
NEON (arm-v7).

Signed-off-by: Alexandr Guzhva <alexanderguzhva@gmail.com>
pull/32191/head
Alexander Guzhva 2024-04-11 22:01:20 -04:00 committed by GitHub
parent 5b45debb28
commit a72a9cd9cb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 172 additions and 73 deletions

View File

@ -29,15 +29,12 @@ elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm*")
list(APPEND BITSET_SRCS
detail/platform/arm/neon-inst.cpp
detail/platform/arm/sve-inst.cpp
detail/platform/arm/instruction_set.cpp
)
# targeting AWS graviton,
# https://github.com/aws/aws-graviton-getting-started/blob/main/c-c%2B%2B.md
# let dynamic.cpp know that SVE is available
# comment it out for now
# set_source_files_properties(detail/platform/dynamic.cpp PROPERTIES COMPILE_FLAGS "-mcpu=neoverse-v1")
set_source_files_properties(detail/platform/arm/sve-inst.cpp PROPERTIES COMPILE_FLAGS "-mcpu=neoverse-v1")
endif()

View File

@ -0,0 +1,56 @@
// Licensed to the LF AI & Data foundation under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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 "instruction_set.h"
#ifdef __linux__
#include <sys/auxv.h>
#endif
namespace milvus {
namespace bitset {
namespace detail {
namespace arm {
InstructionSet::InstructionSet() {
}
#ifdef __linux__
#if defined(HWCAP_SVE)
bool
InstructionSet::supports_sve() {
const unsigned long cap = getauxval(AT_HWCAP);
return ((cap & HWCAP_SVE) == HWCAP_SVE);
}
#else
bool
InstructionSet::supports_sve() {
return false;
}
#endif
#else
bool
InstructionSet::supports_sve() {
return false;
}
#endif
} // namespace arm
} // namespace detail
} // namespace bitset
} // namespace milvus

View File

@ -0,0 +1,43 @@
// Licensed to the LF AI & Data foundation under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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
namespace milvus {
namespace bitset {
namespace detail {
namespace arm {
class InstructionSet {
public:
static InstructionSet&
GetInstance() {
static InstructionSet inst;
return inst;
}
private:
InstructionSet();
public:
bool
supports_sve();
};
} // namespace arm
} // namespace detail
} // namespace bitset
} // namespace milvus

View File

@ -19,6 +19,7 @@
#include "bitset/common.h"
#ifndef BITSET_HEADER_ONLY
#ifdef __ARM_NEON
#include "neon-decl.h"
#include "neon-impl.h"
@ -197,3 +198,4 @@ ALL_ARITH_CMP_OPS(INSTANTIATE_ARITH_COMPARE_NEON, double)
} // namespace milvus
#endif
#endif

View File

@ -19,6 +19,7 @@
#include "bitset/common.h"
#ifndef BITSET_HEADER_ONLY
#ifdef __ARM_FEATURE_SVE
#include "sve-decl.h"
#include "sve-impl.h"
@ -197,3 +198,4 @@ ALL_ARITH_CMP_OPS(INSTANTIATE_ARITH_COMPARE_SVE, double)
} // namespace milvus
#endif
#endif

View File

@ -29,11 +29,9 @@ using namespace milvus::bitset::detail::x86;
#endif
#if defined(__aarch64__)
#include "arm/instruction_set.h"
#include "arm/neon.h"
#ifdef __ARM_FEATURE_SVE
#include "arm/sve.h"
#endif
using namespace milvus::bitset::detail::arm;
@ -480,6 +478,71 @@ init_dynamic_hook() {
#endif
#if defined(__aarch64__)
// sve
if (arm::InstructionSet::GetInstance().supports_sve()) {
#define SET_OP_COMPARE_COLUMN_SVE(TTYPE, UTYPE, OP) \
op_compare_column_##TTYPE##_##UTYPE##_##OP = VectorizedSve:: \
template op_compare_column<TTYPE, UTYPE, CompareOpType::OP>;
#define SET_OP_COMPARE_VAL_SVE(TTYPE, OP) \
op_compare_val_##TTYPE##_##OP = \
VectorizedSve::template op_compare_val<TTYPE, CompareOpType::OP>;
#define SET_OP_WITHIN_RANGE_COLUMN_SVE(TTYPE, OP) \
op_within_range_column_##TTYPE##_##OP = \
VectorizedSve::template op_within_range_column<TTYPE, RangeType::OP>;
#define SET_OP_WITHIN_RANGE_VAL_SVE(TTYPE, OP) \
op_within_range_val_##TTYPE##_##OP = \
VectorizedSve::template op_within_range_val<TTYPE, RangeType::OP>;
#define SET_ARITH_COMPARE_SVE(TTYPE, AOP, CMPOP) \
op_arith_compare_##TTYPE##_##AOP##_##CMPOP = \
VectorizedSve::template op_arith_compare<TTYPE, \
ArithOpType::AOP, \
CompareOpType::CMPOP>;
// assign SVE-related pointers
ALL_COMPARE_OPS(SET_OP_COMPARE_COLUMN_SVE, int8_t, int8_t)
ALL_COMPARE_OPS(SET_OP_COMPARE_COLUMN_SVE, int16_t, int16_t)
ALL_COMPARE_OPS(SET_OP_COMPARE_COLUMN_SVE, int32_t, int32_t)
ALL_COMPARE_OPS(SET_OP_COMPARE_COLUMN_SVE, int64_t, int64_t)
ALL_COMPARE_OPS(SET_OP_COMPARE_COLUMN_SVE, float, float)
ALL_COMPARE_OPS(SET_OP_COMPARE_COLUMN_SVE, double, double)
ALL_COMPARE_OPS(SET_OP_COMPARE_VAL_SVE, int8_t)
ALL_COMPARE_OPS(SET_OP_COMPARE_VAL_SVE, int16_t)
ALL_COMPARE_OPS(SET_OP_COMPARE_VAL_SVE, int32_t)
ALL_COMPARE_OPS(SET_OP_COMPARE_VAL_SVE, int64_t)
ALL_COMPARE_OPS(SET_OP_COMPARE_VAL_SVE, float)
ALL_COMPARE_OPS(SET_OP_COMPARE_VAL_SVE, double)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_COLUMN_SVE, int8_t)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_COLUMN_SVE, int16_t)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_COLUMN_SVE, int32_t)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_COLUMN_SVE, int64_t)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_COLUMN_SVE, float)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_COLUMN_SVE, double)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_VAL_SVE, int8_t)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_VAL_SVE, int16_t)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_VAL_SVE, int32_t)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_VAL_SVE, int64_t)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_VAL_SVE, float)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_VAL_SVE, double)
ALL_ARITH_CMP_OPS(SET_ARITH_COMPARE_SVE, int8_t)
ALL_ARITH_CMP_OPS(SET_ARITH_COMPARE_SVE, int16_t)
ALL_ARITH_CMP_OPS(SET_ARITH_COMPARE_SVE, int32_t)
ALL_ARITH_CMP_OPS(SET_ARITH_COMPARE_SVE, int64_t)
ALL_ARITH_CMP_OPS(SET_ARITH_COMPARE_SVE, float)
ALL_ARITH_CMP_OPS(SET_ARITH_COMPARE_SVE, double)
#undef SET_OP_COMPARE_COLUMN_SVE
#undef SET_OP_COMPARE_VAL_SVE
#undef SET_OP_WITHIN_RANGE_COLUMN_SVE
#undef SET_OP_WITHIN_RANGE_VAL_SVE
#undef SET_ARITH_COMPARE_SVE
return;
}
// neon ?
{
#define SET_OP_COMPARE_COLUMN_NEON(TTYPE, UTYPE, OP) \
@ -541,74 +604,10 @@ init_dynamic_hook() {
#undef SET_OP_WITHIN_RANGE_COLUMN_NEON
#undef SET_OP_WITHIN_RANGE_VAL_NEON
#undef SET_ARITH_COMPARE_NEON
return;
}
#ifdef __ARM_FEATURE_SVE
// sve?
{
#define SET_OP_COMPARE_COLUMN_SVE(TTYPE, UTYPE, OP) \
op_compare_column_##TTYPE##_##UTYPE##_##OP = VectorizedSve:: \
template op_compare_column<TTYPE, UTYPE, CompareOpType::OP>;
#define SET_OP_COMPARE_VAL_SVE(TTYPE, OP) \
op_compare_val_##TTYPE##_##OP = \
VectorizedSve::template op_compare_val<TTYPE, CompareOpType::OP>;
#define SET_OP_WITHIN_RANGE_COLUMN_SVE(TTYPE, OP) \
op_within_range_column_##TTYPE##_##OP = \
VectorizedSve::template op_within_range_column<TTYPE, RangeType::OP>;
#define SET_OP_WITHIN_RANGE_VAL_SVE(TTYPE, OP) \
op_within_range_val_##TTYPE##_##OP = \
VectorizedSve::template op_within_range_val<TTYPE, RangeType::OP>;
#define SET_ARITH_COMPARE_SVE(TTYPE, AOP, CMPOP) \
op_arith_compare_##TTYPE##_##AOP##_##CMPOP = \
VectorizedSve::template op_arith_compare<TTYPE, \
ArithOpType::AOP, \
CompareOpType::CMPOP>;
// assign SVE-related pointers
ALL_COMPARE_OPS(SET_OP_COMPARE_COLUMN_SVE, int8_t, int8_t)
ALL_COMPARE_OPS(SET_OP_COMPARE_COLUMN_SVE, int16_t, int16_t)
ALL_COMPARE_OPS(SET_OP_COMPARE_COLUMN_SVE, int32_t, int32_t)
ALL_COMPARE_OPS(SET_OP_COMPARE_COLUMN_SVE, int64_t, int64_t)
ALL_COMPARE_OPS(SET_OP_COMPARE_COLUMN_SVE, float, float)
ALL_COMPARE_OPS(SET_OP_COMPARE_COLUMN_SVE, double, double)
ALL_COMPARE_OPS(SET_OP_COMPARE_VAL_SVE, int8_t)
ALL_COMPARE_OPS(SET_OP_COMPARE_VAL_SVE, int16_t)
ALL_COMPARE_OPS(SET_OP_COMPARE_VAL_SVE, int32_t)
ALL_COMPARE_OPS(SET_OP_COMPARE_VAL_SVE, int64_t)
ALL_COMPARE_OPS(SET_OP_COMPARE_VAL_SVE, float)
ALL_COMPARE_OPS(SET_OP_COMPARE_VAL_SVE, double)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_COLUMN_SVE, int8_t)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_COLUMN_SVE, int16_t)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_COLUMN_SVE, int32_t)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_COLUMN_SVE, int64_t)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_COLUMN_SVE, float)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_COLUMN_SVE, double)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_VAL_SVE, int8_t)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_VAL_SVE, int16_t)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_VAL_SVE, int32_t)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_VAL_SVE, int64_t)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_VAL_SVE, float)
ALL_RANGE_OPS(SET_OP_WITHIN_RANGE_VAL_SVE, double)
ALL_ARITH_CMP_OPS(SET_ARITH_COMPARE_SVE, int8_t)
ALL_ARITH_CMP_OPS(SET_ARITH_COMPARE_SVE, int16_t)
ALL_ARITH_CMP_OPS(SET_ARITH_COMPARE_SVE, int32_t)
ALL_ARITH_CMP_OPS(SET_ARITH_COMPARE_SVE, int64_t)
ALL_ARITH_CMP_OPS(SET_ARITH_COMPARE_SVE, float)
ALL_ARITH_CMP_OPS(SET_ARITH_COMPARE_SVE, double)
#undef SET_OP_COMPARE_COLUMN_SVE
#undef SET_OP_COMPARE_VAL_SVE
#undef SET_OP_WITHIN_RANGE_COLUMN_SVE
#undef SET_OP_WITHIN_RANGE_VAL_SVE
#undef SET_ARITH_COMPARE_SVE
}
#endif
#endif
}