CPU信息库
cpuinfo是一个用于检测主机CPU性能优化所需关键信息的库。
特性
- 跨平台可用性:
- Linux、Windows、macOS、Android和iOS操作系统
- x86、x86-64、ARM和ARM64架构
- 现代C/C++接口
- 线程安全
- 初始化后无内存分配
- 不抛出异常
- 检测支持的指令集,最高支持AVX512(x86)和ARMv8.3扩展
- 检测SoC和核心信息:
- 处理器(SoC)名称
- 每个CPU核心的厂商和微架构
- 每个CPU核心的ID(ARM上的MIDR,x86上的CPUID叶1 EAX值)
- 检测缓存信息:
- 缓存类型(指令/数据/统一)、大小和线大小
- 缓存关联度
- 共享缓存的核心和逻辑处理器(超线程)
- 检测拓扑信息(逻辑处理器、核心和处理器封装之间的关系)
- 经过充分测试的生产质量代码:
- 60多个基于真实设备数据的模拟测试
- 包含针对硬件和操作系统内核常见错误的解决方案
- 支持具有异构核心的系统,如big.LITTLE和Max.Med.Min
- 宽松的开源许可证(简化版BSD)
示例
记录处理器名称:
cpuinfo_initialize();
printf("运行在%s CPU上\n", cpuinfo_get_package(0)->name);
检测目标是否为32位或64位ARM系统:
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
/* 32位ARM特定代码在此 */
#endif
检查主机CPU是否支持ARM NEON
cpuinfo_initialize();
if (cpuinfo_has_arm_neon()) {
neon_implementation(arguments);
}
检查主机CPU是否支持x86 AVX
cpuinfo_initialize();
if (cpuinfo_has_x86_avx()) {
avx_implementation(arguments);
}
检查线程是否在Cortex-A53核心上运行
cpuinfo_initialize();
switch (cpuinfo_get_current_core()->uarch) {
case cpuinfo_uarch_cortex_a53:
cortex_a53_implementation(arguments);
break;
default:
generic_implementation(arguments);
break;
}
获取处理器中最快核心(如big.LITTLE ARM系统中的大核心)的一级数据缓存大小:
cpuinfo_initialize();
const size_t l1_size = cpuinfo_get_processor(0)->cache.l1d->size;
将线程固定到与当前核心共享二级缓存的核心上(Linux或Android)
cpuinfo_initialize();
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);
const struct cpuinfo_cache* current_l2 = cpuinfo_get_current_processor()->cache.l2;
for (uint32_t i = 0; i < current_l2->processor_count; i++) {
CPU_SET(cpuinfo_get_processor(current_l2->processor_start + i)->linux_id, &cpu_set);
}
pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpu_set);
通过pkg-config使用
如果你想以可移植的方式为项目的构建环境提供必要的编译器和链接器标志,该库默认在构建时启用CPUINFO_BUILD_PKG_CONFIG
并生成pkg-config清单(libcpuinfo.pc)。以下是几个使用示例:
命令行
如果你使用发行版的包管理器安装了该库,可以通过以下方式验证它是否可用于你的构建环境:
$ pkg-config --cflags --libs libcpuinfo
-I/usr/include/x86_64-linux-gnu/ -L/lib/x86_64-linux-gnu/ -lcpuinfo
如果你从源代码安装了该库到非标准位置,pkg-config可能需要帮助找到它:
$ PKG_CONFIG_PATH="/home/me/projects/cpuinfo/prefix/lib/pkgconfig/:$PKG_CONFIG_PATH" pkg-config --cflags --libs libcpuinfo
-I/home/me/projects/cpuinfo/prefix/include -L/home/me/projects/cpuinfo/prefix/lib -lcpuinfo
GNU Autotools
要在GNU Autotools中使用,在项目的configure.ac
中包含以下片段:
# CPU信息库...
PKG_CHECK_MODULES(
[libcpuinfo], [libcpuinfo], [],
[AC_MSG_ERROR([缺少libcpuinfo...])])
YOURPROJECT_CXXFLAGS="$YOURPROJECT_CXXFLAGS $libcpuinfo_CFLAGS"
YOURPROJECT_LIBS="$YOURPROJECT_LIBS $libcpuinfo_LIBS"
Meson
要在Meson中使用,只需将dependency('libcpuinfo')
作为可执行文件的依赖项添加即可。
project(
'MyCpuInfoProject',
'cpp',
meson_version: '>=0.55.0'
)
executable(
'MyCpuInfoExecutable',
sources: 'main.cpp',
dependencies: dependency('libcpuinfo')
)
Bazel
本项目可以使用Bazel构建。
你也可以将此库作为Bazel项目的依赖项。在WORKSPACE
文件中添加:
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
git_repository(
name = "org_pytorch_cpuinfo",
branch = "master",
remote = "https://github.com/Vertexwahn/cpuinfo.git",
)
在BUILD
文件中添加:
cc_binary(
name = "cpuinfo_test",
srcs = [
# ...
],
deps = [
"@org_pytorch_cpuinfo//:cpuinfo",
],
)
CMake
要在CMake中使用,请使用FindPkgConfig模块。以下是一个示例:
cmake_minimum_required(VERSION 3.6)
project("MyCpuInfoProject")
find_package(PkgConfig)
pkg_check_modules(CpuInfo REQUIRED IMPORTED_TARGET libcpuinfo)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} PkgConfig::CpuInfo)
Makefile
要在普通Makefile中使用,可以直接调用pkg-config通过shell替换提供编译器和链接器标志。
CFLAGS=-g3 -Wall -Wextra -Werror ...
LDFLAGS=-lfoo ...
...
CFLAGS+= $(pkg-config --cflags libcpuinfo)
LDFLAGS+= $(pkg-config --libs libcpuinfo)
暴露的信息
- 处理器(SoC)名称
- 微架构
- 可用指令集
- CPU频率
- 缓存
- 大小
- 关联度
- 线大小
- 分区数
- 标志(统一、包含、复杂哈希函数)
- 拓扑(共享此缓存级别的逻辑处理器)
- TLB
- 条目数
- 关联度
- 覆盖的页面类型(指令、数据)
- 覆盖的页面大小
- 拓扑信息
- 逻辑处理器
- 核心
- 封装(插槽)
支持的环境:
- Android
- x86 ABI
- x86_64 ABI
- armeabi ABI
- armeabiv7-a ABI
- arm64-v8a ABI
-
mips ABI -
mips64 ABI
- Linux
- x86
- x86-64
- 32位 ARM(ARMv5T及以后版本)
- ARM64
- PowerPC64
- iOS
- x86(iPhone模拟器)
- x86-64(iPhone模拟器)
- ARMv7
- ARM64
- macOS
- x86
- x86-64
- ARM64(Apple silicon)
- Windows
- x86
- x86-64
- arm64
方法
- 处理器(SoC)名称检测
- 在x86/x86-64上使用CPUID叶0x80000002–0x80000004
- 在ARM上使用
/proc/cpuinfo
- 使用
ro.chipname
、ro.board.platform
、ro.product.board
、ro.mediatek.platform
、ro.arch
属性(Android) - 在ARM Linux上使用内核日志(
dmesg
) - 在ARM64 Windows上使用Windows注册表
- 厂商和微架构检测
- Intel设计的x86/x86-64核心(最新至Sunny Cove、Goldmont Plus和Knights Mill)
- AMD设计的x86/x86-64核心(最新至Puma/Jaguar和Zen 2)
- VIA设计的x86/x86-64核心
- 其他x86核心(DM&P、RDC、Transmeta、Cyrix、Rise)
- ARM设计的ARM核心(最新至Cortex-A55、Cortex-A77和Neoverse E1/V1/N2/V2)
- 高通设计的ARM核心(Scorpion、Krait和Kryo)
- Nvidia设计的ARM核心(Denver和Carmel)
- 三星设计的ARM核心(Exynos)
- Intel设计的ARM核心(XScale,最新至第3代)
- Apple设计的ARM核心(最新至Lightning和Thunder)
- Cavium设计的ARM核心(ThunderX)
- AppliedMicro设计的ARM核心(X-Gene)
- 指令集检测
- 在x86/x86-64上使用CPUID
- 在32位ARM EABI上使用
/proc/cpuinfo
(Linux) - 在32位ARM上使用微架构启发式方法
- 使用
FPSID
和WCID
寄存器(32位ARM) - 使用
getauxval
(Linux/ARM) - 使用
/proc/self/auxv
(Android/ARM) - 在ARM上使用指令探测(Linux)
- 在ARM64上使用CPUID寄存器(Linux)
- 在ARM64 Windows上使用IsProcessorFeaturePresent
- 缓存检测
- 在x86/x86-64上使用CPUID叶0x00000002
- 在非AMD x86/x86-64上使用CPUID叶0x00000004
- 在AMD x86/x86-64上使用CPUID叶0x80000005-0x80000006
- 在AMD x86/x86-64上使用CPUID叶0x8000001D
- 使用
/proc/cpuinfo
(Linux/pre-ARMv7) - 使用微架构启发式方法(ARM)
- 使用芯片组名称(ARM)
- 使用
sysctlbyname
(Mach) - 使用sysfs
typology
目录(ARM/Linux) - 使用sysfs
cache
目录(Linux) - 在ARM64 Windows上使用
GetLogicalProcessorInformationEx
- TLB检测
- 在x86/x86-64上使用CPUID叶0x00000002
- 在AMD x86/x86-64上使用CPUID叶0x80000005-0x80000006和0x80000019
- 使用微架构启发式方法(ARM)
- 拓扑检测
- 在x86/x86-64上使用CPUID叶0x00000001(传统APIC ID)
- 在x86/x86-64上使用CPUID叶0x0000000B(Intel APIC ID)
- 在x86/x86-64上使用CPUID叶0x8000001E(AMD APIC ID)
- 使用
/proc/cpuinfo
(Linux) - 使用
host_info
(Mach) - 使用
GetLogicalProcessorInformationEx
(Windows) - 使用sysfs(Linux)
- 使用芯片组名称(ARM/Linux)