Read cpu flags from /proc/cpuinfo
This commit is contained in:
parent
188adc9c0d
commit
190b8c20db
8
deps/oblib/src/common/ob_target_specific.h
vendored
8
deps/oblib/src/common/ob_target_specific.h
vendored
@ -218,16 +218,16 @@ OB_DECLARE_AVX512_SPECIFIC_CODE(
|
||||
OB_INLINE uint32_t get_supported_archs()
|
||||
{
|
||||
uint32_t result = 0;
|
||||
if (ObCpuFlagsCache::support_sse42()) {
|
||||
if (CpuFlagSet::get_instance().have_flag(CpuFlag::SSE4_2)) {
|
||||
result |= static_cast<uint32_t>(ObTargetArch::SSE42);
|
||||
}
|
||||
if (ObCpuFlagsCache::support_avx()) {
|
||||
if (CpuFlagSet::get_instance().have_flag(CpuFlag::AVX)) {
|
||||
result |= static_cast<uint32_t>(ObTargetArch::AVX);
|
||||
}
|
||||
if (ObCpuFlagsCache::support_avx2()) {
|
||||
if (CpuFlagSet::get_instance().have_flag(CpuFlag::AVX2)) {
|
||||
result |= static_cast<uint32_t>(ObTargetArch::AVX2);
|
||||
}
|
||||
if (ObCpuFlagsCache::support_avx512()) {
|
||||
if (CpuFlagSet::get_instance().have_flag(CpuFlag::AVX512BW)) {
|
||||
result |= static_cast<uint32_t>(ObTargetArch::AVX512);
|
||||
}
|
||||
return result;
|
||||
|
149
deps/oblib/src/lib/cpu/ob_cpu_topology.cpp
vendored
149
deps/oblib/src/lib/cpu/ob_cpu_topology.cpp
vendored
@ -12,12 +12,8 @@
|
||||
|
||||
#include "lib/cpu/ob_cpu_topology.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include "lib/ob_define.h"
|
||||
|
||||
using namespace oceanbase::common;
|
||||
#include "lib/container/ob_bit_set.h"
|
||||
|
||||
namespace oceanbase {
|
||||
namespace common {
|
||||
@ -26,6 +22,149 @@ int64_t __attribute__((weak)) get_cpu_count()
|
||||
{
|
||||
return get_cpu_num();
|
||||
}
|
||||
|
||||
static bool cpu_haveOSXSAVE();
|
||||
static bool cpu_have_sse42();
|
||||
static bool cpu_have_avx();
|
||||
static bool cpu_have_avx2();
|
||||
static bool cpu_have_avxf();
|
||||
static bool cpu_have_avx512bw();
|
||||
|
||||
const CpuFlagSet& CpuFlagSet::get_instance()
|
||||
{
|
||||
static CpuFlagSet instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
bool CpuFlagSet::have_flag(const CpuFlag flag) const
|
||||
{
|
||||
return flags_ & (1 << (int)flag);
|
||||
}
|
||||
|
||||
CpuFlagSet::CpuFlagSet() : flags_(0)
|
||||
{
|
||||
uint64_t flags_from_cpu = init_from_cpu();
|
||||
uint64_t flags_from_os = init_from_os();
|
||||
if (flags_from_cpu != flags_from_os) {
|
||||
COMMON_LOG_RET(ERROR,
|
||||
OB_ERR_SYS,
|
||||
"There is a mismatch between the cpu flags from cpu and those from os, "
|
||||
"ISA extension like avx512bw may be not supported by your virtualization setup");
|
||||
flags_ = flags_from_cpu & flags_from_os;
|
||||
} else {
|
||||
flags_ = flags_from_cpu;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t CpuFlagSet::init_from_cpu()
|
||||
{
|
||||
uint64_t flags = 0;
|
||||
#define cpu_have(flag, FLAG) \
|
||||
if (cpu_have_##flag()) { \
|
||||
flags |= (1 << (int)CpuFlag::FLAG); \
|
||||
}
|
||||
cpu_have(sse42, SSE4_2);
|
||||
cpu_have(avx, AVX);
|
||||
cpu_have(avx2, AVX2);
|
||||
cpu_have(avx512bw, AVX512BW);
|
||||
return flags;
|
||||
}
|
||||
|
||||
uint64_t CpuFlagSet::init_from_os()
|
||||
{
|
||||
uint64_t flags = 0;
|
||||
int ret = OB_SUCCESS;
|
||||
const char* const CPU_FLAG_CMDS[(int)CpuFlag::MAX] = {
|
||||
"grep -E ' sse4_2( |$)' /proc/cpuinfo",
|
||||
"grep -E ' avx( |$)' /proc/cpuinfo",
|
||||
"grep -E ' avx2( |$)' /proc/cpuinfo",
|
||||
"grep -E ' avx512bw( |$)' /proc/cpuinfo"};
|
||||
for (int i = 0; i < (int)CpuFlag::MAX; ++i) {
|
||||
flags |= (0 == system(CPU_FLAG_CMDS[i])) << i;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
#if defined(__x86_64__)
|
||||
void get_cpuid(int reg[4], int func_id)
|
||||
{
|
||||
__asm__("cpuid\n\t"
|
||||
: "=a"(reg[0]), "=b"(reg[1]), "=c"(reg[2]),
|
||||
"=d"(reg[3])
|
||||
: "a"(func_id), "c"(0));
|
||||
}
|
||||
uint64_t our_xgetbv(uint32_t xcr) noexcept
|
||||
{
|
||||
uint32_t eax;
|
||||
uint32_t edx;
|
||||
__asm__ volatile("xgetbv"
|
||||
: "=a"(eax), "=d"(edx)
|
||||
: "c"(xcr));
|
||||
return (static_cast<uint64_t>(edx) << 32) | eax;
|
||||
}
|
||||
#endif
|
||||
bool cpu_haveOSXSAVE()
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
int regs[4];
|
||||
get_cpuid(regs, 0x1);
|
||||
return (regs[2] >> 27) & 1u;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
bool cpu_have_sse42()
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
int regs[4];
|
||||
get_cpuid(regs, 0x1);
|
||||
return regs[2] >> 20 & 1;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
bool cpu_have_avx()
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
int regs[4];
|
||||
get_cpuid(regs, 0x1);
|
||||
return cpu_haveOSXSAVE() && ((our_xgetbv(0) & 6u) == 6u) && (regs[2] >> 28 & 1);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
bool cpu_have_avx2()
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
int regs[4];
|
||||
get_cpuid(regs, 0x7);
|
||||
return cpu_have_avx() && (regs[1] >> 5 & 1);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
bool cpu_have_avx512f()
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
int regs[4];
|
||||
get_cpuid(regs, 0x7);
|
||||
return regs[1] >> 16 & 1;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
bool cpu_have_avx512bw()
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
int regs[4];
|
||||
get_cpuid(regs, 0x7);
|
||||
return cpu_have_avx512f() && (regs[1] >> 30 & 1);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
} // common
|
||||
} // oceanbase
|
||||
|
||||
|
123
deps/oblib/src/lib/cpu/ob_cpu_topology.h
vendored
123
deps/oblib/src/lib/cpu/ob_cpu_topology.h
vendored
@ -13,124 +13,29 @@
|
||||
#ifndef OCEANBASE_LIB_OB_CPU_TOPOLOGY_
|
||||
#define OCEANBASE_LIB_OB_CPU_TOPOLOGY_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "lib/utility/ob_macro_utils.h"
|
||||
#include "lib/utility/utility.h"
|
||||
|
||||
#include "lib/container/ob_bit_set.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
|
||||
int64_t get_cpu_count();
|
||||
|
||||
#if defined(__x86_64__)
|
||||
inline void get_cpuid(int reg[4], int func_id)
|
||||
{
|
||||
__asm__("cpuid\n\t"
|
||||
: "=a"(reg[0]), "=b"(reg[1]), "=c"(reg[2]),
|
||||
"=d"(reg[3])
|
||||
: "a"(func_id), "c"(0));
|
||||
}
|
||||
inline uint64_t our_xgetbv(uint32_t xcr) noexcept
|
||||
{
|
||||
uint32_t eax;
|
||||
uint32_t edx;
|
||||
__asm__ volatile("xgetbv"
|
||||
: "=a"(eax), "=d"(edx)
|
||||
: "c"(xcr));
|
||||
return (static_cast<uint64_t>(edx) << 32) | eax;
|
||||
}
|
||||
#endif
|
||||
inline bool haveOSXSAVE();
|
||||
inline bool have_sse42();
|
||||
inline bool have_avx();
|
||||
inline bool have_avx2();
|
||||
inline bool have_avxf();
|
||||
inline bool have_avx512bw();
|
||||
|
||||
inline bool haveOSXSAVE()
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
int regs[4];
|
||||
get_cpuid(regs, 0x1);
|
||||
return (regs[2] >> 27) & 1u;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool have_sse42()
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
int regs[4];
|
||||
get_cpuid(regs, 0x1);
|
||||
return regs[2] >> 20 & 1;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
inline bool have_avx()
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
int regs[4];
|
||||
get_cpuid(regs, 0x1);
|
||||
return haveOSXSAVE() && ((our_xgetbv(0) & 6u) == 6u) && (regs[2] >> 28 & 1);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
inline bool have_avx2()
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
int regs[4];
|
||||
get_cpuid(regs, 0x7);
|
||||
return have_avx() && (regs[1] >> 5 & 1);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
inline bool have_avx512f()
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
int regs[4];
|
||||
get_cpuid(regs, 0x7);
|
||||
return regs[1] >> 16 & 1;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
inline bool have_avx512bw()
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
int regs[4];
|
||||
get_cpuid(regs, 0x7);
|
||||
return have_avx512f() && (regs[1] >> 30 & 1);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct ObCpuFlagsCache
|
||||
{
|
||||
static inline bool support_sse42() {
|
||||
static const bool is_supported = have_sse42();
|
||||
return is_supported;
|
||||
}
|
||||
|
||||
static inline bool support_avx() {
|
||||
static const bool is_supported = have_avx();
|
||||
return is_supported;
|
||||
}
|
||||
|
||||
static inline bool support_avx2() {
|
||||
static const bool is_supported = have_avx2();
|
||||
return is_supported;
|
||||
}
|
||||
|
||||
static inline bool support_avx512() {
|
||||
static const bool is_supported = have_avx512bw();
|
||||
return is_supported;
|
||||
}
|
||||
enum class CpuFlag { SSE4_2 = 0, AVX, AVX2, AVX512BW, MAX };
|
||||
class CpuFlagSet {
|
||||
public:
|
||||
DISABLE_COPY_ASSIGN(CpuFlagSet);
|
||||
static const CpuFlagSet& get_instance();
|
||||
bool have_flag(const CpuFlag flag) const;
|
||||
private:
|
||||
CpuFlagSet();
|
||||
uint64_t init_from_cpu();
|
||||
uint64_t init_from_os();
|
||||
int64_t flags_;
|
||||
};
|
||||
|
||||
} // namespace common
|
||||
|
Loading…
x
Reference in New Issue
Block a user