Skip to content
Merged
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
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,6 @@
[submodule "contrib/zlib-ng"]
path = contrib/zlib-ng
url = https://github.com/zlib-ng/zlib-ng
[submodule "contrib/cpu_features"]
path = contrib/cpu_features
url = https://github.com/google/cpu_features
7 changes: 5 additions & 2 deletions contrib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ add_library(cpptoml INTERFACE)
target_include_directories(cpptoml INTERFACE
${PROJECT_SOURCE_DIR}/contrib/cpptoml)

SET (BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "Disable google-benchmark testing")
SET (BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE BOOL "Disable google-benchmark testing")
SET (BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "Disable google-benchmark testing" FORCE)
SET (BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE BOOL "Disable google-benchmark testing" FORCE)
add_subdirectory(benchmark)

set (BUILD_TESTING OFF CACHE BOOL "Disable cpu-features testing" FORCE)
add_subdirectory(cpu_features)
1 change: 1 addition & 0 deletions contrib/cpu_features
Submodule cpu_features added at e38dc6
14 changes: 8 additions & 6 deletions dbms/src/Common/TargetSpecific.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ struct AVXChecker
{
__attribute__((pure, always_inline)) static bool runtimeSupport()
{
return simd_option::ENABLE_AVX && __builtin_cpu_supports("avx2");
return simd_option::ENABLE_AVX && common::cpu_feature_flags.avx2;
}
};
#else
Expand Down Expand Up @@ -150,11 +150,12 @@ struct AVX512Checker
{
__attribute__((pure, always_inline)) static bool runtimeSupport()
{
using namespace common;
return simd_option::ENABLE_AVX512
&& __builtin_cpu_supports("avx512f")
&& __builtin_cpu_supports("avx512bw")
&& __builtin_cpu_supports("avx512vl")
&& __builtin_cpu_supports("avx512cd");
&& common::cpu_feature_flags.avx512f
&& common::cpu_feature_flags.avx512bw
&& common::cpu_feature_flags.avx512vl
&& common::cpu_feature_flags.avx512cd;
}
};
#else
Expand Down Expand Up @@ -190,7 +191,8 @@ struct SSE4Checker
{
__attribute__((pure, always_inline)) static bool runtimeSupport()
{
return __builtin_cpu_supports("sse4.2");
return common::cpu_feature_flags.sse4_1
&& common::cpu_feature_flags.sse4_2;
}
};
#else
Expand Down
4 changes: 4 additions & 0 deletions libs/libcommon/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ add_library (common ${SPLIT_SHARED}
src/crc64_avx512.cpp
src/crc64.cpp
src/simd.cpp
src/detect_features.cpp

include/common/types.h
include/common/DateLUT.h
Expand All @@ -63,6 +64,7 @@ add_library (common ${SPLIT_SHARED}
include/common/crc64_table.h
include/common/crc64_fast.h
include/common/crc64.h
include/common/detect_features.h

include/ext/bit_cast.h
include/ext/collection_cast.h
Expand Down Expand Up @@ -122,6 +124,7 @@ target_include_directories (common BEFORE PUBLIC ${Boost_INCLUDE_DIRS})

target_link_libraries (
common
PUBLIC
pocoext
${CITYHASH_LIBRARIES}
${CCTZ_LIBRARY}
Expand All @@ -132,6 +135,7 @@ target_link_libraries (
${GLIBC_COMPATIBILITY_LIBRARIES}
${MEMCPY_LIBRARIES}
fmt
cpu_features
)

if (RT_LIBRARY)
Expand Down
25 changes: 25 additions & 0 deletions libs/libcommon/include/common/detect_features.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#if defined(__aarch64__) || defined(__arm64__) || defined(__arm64) || defined(__ARM64) || defined(__AARCH64__)
#include <cpuinfo_aarch64.h>
namespace common
{
using CPUFeatures = cpu_features::Aarch64Features;
using CPUFeature = cpu_features::Aarch64FeaturesEnum;
using CPUInfo = cpu_features::Aarch64Info;
extern const CPUInfo cpu_info;
static inline const CPUFeatures & cpu_feature_flags = cpu_info.features;
} // namespace common
#endif

#if defined(__x86_64__) || defined(__x86_64) || defined(__amd64) || defined(__amd64__)
#include <cpuinfo_x86.h>
namespace common
{
using CPUFeatures = cpu_features::X86Features;
using CPUFeature = cpu_features::X86FeaturesEnum;
using CPUInfo = cpu_features::X86Info;
extern const CPUInfo cpu_info;
static inline const CPUFeatures & cpu_feature_flags = cpu_info.features;
} // namespace common
#endif
16 changes: 9 additions & 7 deletions libs/libcommon/include/common/mem_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ __attribute__((always_inline, pure)) inline bool memoryEqualSSE2(const char * p1
/// relatively old libc.
__attribute__((always_inline, pure)) inline bool memoryEqual(const char * p1, const char * p2, size_t size) noexcept
{
using namespace common;
if (p1 == p2)
return true;

Expand All @@ -133,14 +134,14 @@ __attribute__((always_inline, pure)) inline bool memoryEqual(const char * p1, co
#ifdef TIFLASH_ENABLE_ASIMD_SUPPORT
// for ASIMD target, it is a little bit different because all the compare function is defined in a
// separate file other than the main loop itself.
if (ENABLE_ASIMD && SIMDRuntimeSupport(SIMDFeature::asimd))
if (ENABLE_ASIMD && cpu_feature_flags.asimd)
{
return _detail::memoryEqualASIMD(p1, p2, size);
}
#endif

#ifdef TIFLASH_ENABLE_AVX512_SUPPORT
if (ENABLE_AVX512 && SIMDRuntimeSupport(SIMDFeature::avx512f) && SIMDRuntimeSupport(SIMDFeature::avx512vl))
if (ENABLE_AVX512 && cpu_feature_flags.avx512f && cpu_feature_flags.avx512vl)
{
if (!_detail::memoryEqualAVX512x4Loop(p1, p2, size))
{
Expand All @@ -150,7 +151,7 @@ __attribute__((always_inline, pure)) inline bool memoryEqual(const char * p1, co
}
#endif
#ifdef TIFLASH_ENABLE_AVX_SUPPORT
if (ENABLE_AVX && SIMDRuntimeSupport(SIMDFeature::avx2))
if (ENABLE_AVX && cpu_feature_flags.avx2)
{
if (!_detail::memoryEqualAVX2x4Loop(p1, p2, size))
{
Expand Down Expand Up @@ -223,18 +224,19 @@ __attribute__((always_inline, pure)) inline bool memoryIsByteGeneric(const void
__attribute__((always_inline, pure)) inline bool memoryIsByte(const void * data, size_t size, std::byte target)
{
using namespace simd_option;
using namespace common;
if (size == 0)
return true;

#ifdef TIFLASH_ENABLE_AVX512_SUPPORT
if (size >= /* sizeof(_m512i) */ 64 && ENABLE_AVX512 && SIMDRuntimeSupport(SIMDFeature::avx512vl)
&& SIMDRuntimeSupport(SIMDFeature::avx512bw))
if (size >= /* sizeof(_m512i) */ 64 && ENABLE_AVX512 && cpu_feature_flags.avx512vl
&& cpu_feature_flags.avx512bw)
{
return _detail::memoryIsByteAVX512(data, size, target);
}
#endif
#ifdef TIFLASH_ENABLE_AVX_SUPPORT
if (size >= /* sizeof(_m256i) */ 32 && ENABLE_AVX && SIMDRuntimeSupport(SIMDFeature::avx2))
if (size >= /* sizeof(_m256i) */ 32 && ENABLE_AVX && cpu_feature_flags.avx2)
{
return _detail::memoryIsByteAVX2(data, size, target);
}
Expand All @@ -246,7 +248,7 @@ __attribute__((always_inline, pure)) inline bool memoryIsByte(const void * data,
}
#endif
#if TIFLASH_ENABLE_ASIMD_SUPPORT
if (size > /* sizeof(uint8x16_t) */ 16 && ENABLE_ASIMD && SIMDRuntimeSupport(SIMDFeature::asimd))
if (size > /* sizeof(uint8x16_t) */ 16 && ENABLE_ASIMD && cpu_feature_flags.asimd)
{
return _detail::memoryIsByteASIMD(data, size, target);
}
Expand Down
91 changes: 1 addition & 90 deletions libs/libcommon/include/common/simd.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
#pragma once
#if defined(__aarch64__)
#if __has_include(<asm/hwcap.h>)
#include <asm/hwcap.h>
#include <sys/auxv.h>
#endif
#endif
#include <common/detect_features.h>
namespace simd_option
{
#if defined(__x86_64__)
Expand All @@ -17,44 +12,6 @@ extern bool ENABLE_AVX;
extern bool ENABLE_AVX512;
#endif

/// @attention: we keeps the SIMDFeature encoding consistent,
/// so even if the feature is not enabled, we still define an enum item for it
enum class SIMDFeature
{
avx,
avx2,
avx512f,
avx512dq,
avx512cd,
avx512bw,
avx512vl
};

static inline bool SIMDRuntimeSupport(SIMDFeature feature)
{
// Please Check:
// https://gcc.gnu.org/onlinedocs/gcc/x86-Built-in-Functions.html
// GCC itself provides runtime feature checking builtins, but notice
// that GCC 7 does not yet support `avx512vnni`. Since it is not very useful
// up to current stage, we can ignore it for now.
#define CHECK_RETURN(X) \
case SIMDFeature::X: \
return __builtin_cpu_supports(#X);

switch (feature)
{
CHECK_RETURN(avx)
CHECK_RETURN(avx2)
CHECK_RETURN(avx512f)
CHECK_RETURN(avx512dq)
CHECK_RETURN(avx512cd)
CHECK_RETURN(avx512bw)
CHECK_RETURN(avx512vl)
}
#undef CHECK_RETURN
return false;
}

#elif defined(__aarch64__)

#ifdef TIFLASH_ENABLE_ASIMD_SUPPORT
Expand All @@ -64,52 +21,6 @@ extern bool ENABLE_ASIMD;
#ifdef TIFLASH_ENABLE_SVE_SUPPORT
extern bool ENABLE_SVE;
#endif

enum class SIMDFeature
{
asimd,
pmull,
sve,
sve2
};


static inline bool SIMDRuntimeSupport([[maybe_unused]] SIMDFeature feature)
{
/// Notice that we do not detect support for Darwin/arm64 since
/// it does not have HWCAP support. However, if such feature is
/// ever needed in the future, a good reference can be:
/// https://github.com/golang/sys/pull/114
#if __has_include(<asm/hwcap.h>)
unsigned long hwcap;
switch (feature)
{
// Please Check:
// https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h
// AARCH64 targets does not has similar builtins for runtime checking; however, it has
// a full series of HWCAP flags to achieve the similar capability.
// CentOS 7 default kernel does not support SVE2, so we just ignore SVE2 in that case.
// (Maybe one can consider it after ARMv9 becomes more prevalent.)
case SIMDFeature::sve:
hwcap = getauxval(AT_HWCAP);
return hwcap & HWCAP_SVE;
case SIMDFeature::pmull:
hwcap = getauxval(AT_HWCAP);
return hwcap & HWCAP_PMULL;
case SIMDFeature::asimd:
hwcap = getauxval(AT_HWCAP);
return hwcap & HWCAP_ASIMD;
case SIMDFeature::sve2:
#ifdef HWCAP2_SVE2
hwcap = getauxval(AT_HWCAP2);
return hwcap & HWCAP2_SVE2;
#else
return false;
#endif // HWCAP2_SVE2
}
#endif // __has_include(<asm/hwcap.h>)
return false;
}
#endif

/// @todo: notice that currently we use plain SIMD without OOP abstraction:
Expand Down
10 changes: 6 additions & 4 deletions libs/libcommon/src/crc64.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#include <common/crc64.h>
#include <common/crc64_fast.h>
#include <common/crc64_table.h>
#include <common/detect_features.h>
#include <common/simd.h>
namespace crc64
{
using namespace common;
Digest::Digest(Mode mode)
{
// clang-format off
Expand All @@ -12,7 +14,7 @@ Digest::Digest(Mode mode)
#if TIFLASH_COMPILER_VPCLMULQDQ_SUPPORT
#ifdef TIFLASH_ENABLE_AVX512_SUPPORT
if ((mode == Mode::Auto || mode >= Mode::SIMD_512) && ENABLE_AVX512
&& __builtin_cpu_supports("vpclmulqdq") && __builtin_cpu_supports("avx512dq"))
&& cpu_feature_flags.vpclmulqdq && cpu_feature_flags.avx512dq)
{
update_fn = [](uint64_t _state, const void * _src, size_t _length) {
return crc64::_detail::update_fast<512>(crc64::_detail::update_vpclmulqdq_avx512, _state, _src, _length);
Expand All @@ -22,7 +24,7 @@ Digest::Digest(Mode mode)
#endif // TIFLASH_ENABLE_AVX512_SUPPORT
#ifdef TIFLASH_ENABLE_AVX_SUPPORT
if ((mode == Mode::Auto || mode >= Mode::SIMD_256) && ENABLE_AVX
&& __builtin_cpu_supports("vpclmulqdq") && __builtin_cpu_supports("avx2"))
&& cpu_feature_flags.vpclmulqdq && cpu_feature_flags.avx2)
{
update_fn = [](uint64_t _state, const void * _src, size_t _length) {
return crc64::_detail::update_fast<256>(crc64::_detail::update_vpclmulqdq_avx2, _state, _src, _length);
Expand All @@ -37,12 +39,12 @@ Digest::Digest(Mode mode)
return crc64::_detail::update_fast(crc64::_detail::update_simd, _state, _src, _length);
};
#ifdef TIFLASH_ENABLE_ASIMD_SUPPORT
if (!ENABLE_ASIMD || !SIMDRuntimeSupport(SIMDFeature::pmull))
if (!ENABLE_ASIMD || !cpu_feature_flags.pmull)
{
update_fn = _detail::update_table;
}
#else // must be SSE case then
if (!__builtin_cpu_supports("pclmul"))
if (!cpu_feature_flags.pclmulqdq)
{
update_fn = _detail::update_table;
}
Expand Down
12 changes: 12 additions & 0 deletions libs/libcommon/src/detect_features.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include <common/detect_features.h>

namespace common
{
#ifdef CPU_FEATURES_ARCH_AARCH64
const CPUInfo cpu_info = cpu_features::GetAarch64Info();
#endif

#ifdef CPU_FEATURES_ARCH_X86
const CPUInfo cpu_info = cpu_features::GetX86Info();
#endif
} // namespace common
7 changes: 4 additions & 3 deletions libs/libcommon/src/tests/gtest_crc64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ using Cases = std::vector<std::pair<A, B>>;

bool check_basic_support()
{
using namespace common;
#if defined(__x86_64__)
return __builtin_cpu_supports("pclmul");
return cpu_feature_flags.pclmulqdq;
#elif defined(__aarch64__) || defined(__arm64__)
return simd_option::SIMDRuntimeSupport(simd_option::SIMDFeature::asimd)
&& simd_option::SIMDRuntimeSupport(simd_option::SIMDFeature::pmull);
return cpu_feature_flags.asimd
&& cpu_feature_flags.pmull;
#endif
}

Expand Down
7 changes: 4 additions & 3 deletions libs/libcommon/src/tests/gtest_mem_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ TEST(MemUtilsTest, MemoryIsZeroGeneric)
TEST(MemUtilsTest, MemoryIsZeroAVX2)
{
using namespace simd_option;
if (!SIMDRuntimeSupport(SIMDFeature::avx2))
if (!common::cpu_feature_flags.avx2)
{
return GTEST_MESSAGE_("skipped", ::testing::TestPartResult::kSuccess);
}
Expand All @@ -177,7 +177,8 @@ TEST(MemUtilsTest, MemoryIsZeroAVX2)
TEST(MemUtilsTest, MemoryIsZeroAVX512)
{
using namespace simd_option;
if (!SIMDRuntimeSupport(SIMDFeature::avx512vl) || !SIMDRuntimeSupport(SIMDFeature::avx512bw))
if (!common::cpu_feature_flags.avx512vl
|| !common::cpu_feature_flags.avx512bw)
{
return GTEST_MESSAGE_("skipped", ::testing::TestPartResult::kSuccess);
}
Expand Down Expand Up @@ -217,7 +218,7 @@ TEST(MemUtilsTest, MemoryIsZeroSSE2)
TEST(MemUtilsTest, MemoryIsZeroASIMD)
{
using namespace simd_option;
if (!SIMDRuntimeSupport(SIMDFeature::asimd))
if (!common::cpu_feature_flags.asimd)
{
return GTEST_MESSAGE_("skipped", ::testing::TestPartResult::kSuccess);
}
Expand Down