1# cpu_features 2 3A cross-platform C library to retrieve CPU features (such as available 4instructions) at runtime. 5 6# GitHub-CI Status 7 8[comment]: <> (The following lines are generated by "scripts/generate_badges.d" that you can run online https://run.dlang.io/) 9 10| Os | amd64 | AArch64 | ARM | MIPS | POWER | RISCV | s390x | 11| :-- | --: | --: | --: | --: | --: | --: | --: | 12| Linux | [![][i1a0]][l1a0]<br/>[![][i1a1]][l1a1] | [![][i1b0]][l1b0]<br/>![][d1] | [![][i1c0]][l1c0]<br/>![][d1] | [![][i1d0]][l1d0]<br/>![][d1] | [![][i1e0]][l1e0]<br/>![][d1] | [![][i1f0]][l1f0]<br/>![][d1] | [![][i1g0]][l1g0]<br/>![][d1] | 13| FreeBSD | [![][i2a0]][l2a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | 14| MacOS | [![][i3a0]][l3a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | 15| Windows | [![][i4a0]][l4a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | 16 17[d0]: https://img.shields.io/badge/CMake-N%2FA-lightgrey 18[d1]: https://img.shields.io/badge/Bazel-N%2FA-lightgrey 19[i1a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_linux_cmake.yml?branch=main&label=CMake 20[i1a1]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_linux_bazel.yml?branch=main&label=Bazel 21[i1b0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/aarch64_linux_cmake.yml?branch=main&label=CMake 22[i1c0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/arm_linux_cmake.yml?branch=main&label=CMake 23[i1d0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/mips_linux_cmake.yml?branch=main&label=CMake 24[i1e0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/power_linux_cmake.yml?branch=main&label=CMake 25[i1f0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/riscv_linux_cmake.yml?branch=main&label=CMake 26[i1g0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/s390x_linux_cmake.yml?branch=main&label=CMake 27[i2a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_freebsd_cmake.yml?branch=main&label=CMake 28[i3a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_macos_cmake.yml?branch=main&label=CMake 29[i4a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_windows_cmake.yml?branch=main&label=CMake 30[l1a0]: https://github.com/google/cpu_features/actions/workflows/amd64_linux_cmake.yml 31[l1a1]: https://github.com/google/cpu_features/actions/workflows/amd64_linux_bazel.yml 32[l1b0]: https://github.com/google/cpu_features/actions/workflows/aarch64_linux_cmake.yml 33[l1c0]: https://github.com/google/cpu_features/actions/workflows/arm_linux_cmake.yml 34[l1d0]: https://github.com/google/cpu_features/actions/workflows/mips_linux_cmake.yml 35[l1e0]: https://github.com/google/cpu_features/actions/workflows/power_linux_cmake.yml 36[l1f0]: https://github.com/google/cpu_features/actions/workflows/riscv_linux_cmake.yml 37[l1g0]: https://github.com/google/cpu_features/actions/workflows/s390x_linux_cmake.yml 38[l2a0]: https://github.com/google/cpu_features/actions/workflows/amd64_freebsd_cmake.yml 39[l3a0]: https://github.com/google/cpu_features/actions/workflows/amd64_macos_cmake.yml 40[l4a0]: https://github.com/google/cpu_features/actions/workflows/amd64_windows_cmake.yml 41 42## Table of Contents 43 44- [Design Rationale](#rationale) 45- [Code samples](#codesample) 46- [Running sample code](#usagesample) 47- [What's supported](#support) 48- [Android NDK's drop in replacement](#ndk) 49- [License](#license) 50- [Build with cmake](#cmake) 51- [Community Bindings](#bindings) 52 53<a name="rationale"></a> 54## Design Rationale 55 56- **Simple to use.** See the snippets below for examples. 57- **Extensible.** Easy to add missing features or architectures. 58- **Compatible with old compilers** and available on many architectures so it 59 can be used widely. To ensure that cpu_features works on as many platforms 60 as possible, we implemented it in a highly portable version of C: C99. 61- **Sandbox-compatible.** The library uses a variety of strategies to cope 62 with sandboxed environments or when `cpuid` is unavailable. This is useful 63 when running integration tests in hermetic environments. 64- **Thread safe, no memory allocation, and raises no exceptions.** 65 cpu_features is suitable for implementing fundamental libc functions like 66 `malloc`, `memcpy`, and `memcmp`. 67- **Unit tested.** 68 69<a name="codesample"></a> 70## Code samples 71 72**Note:** For C++ code, the library functions are defined in the `cpu_features` namespace. 73 74### Checking features at runtime 75 76Here's a simple example that executes a codepath if the CPU supports both the 77AES and the SSE4.2 instruction sets: 78 79```c 80#include "cpuinfo_x86.h" 81 82// For C++, add `using namespace cpu_features;` 83static const X86Features features = GetX86Info().features; 84 85void Compute(void) { 86 if (features.aes && features.sse4_2) { 87 // Run optimized code. 88 } else { 89 // Run standard code. 90 } 91} 92``` 93 94### Caching for faster evaluation of complex checks 95 96If you wish, you can read all the features at once into a global variable, and 97then query for the specific features you care about. Below, we store all the ARM 98features and then check whether AES and NEON are supported. 99 100```c 101#include <stdbool.h> 102#include "cpuinfo_arm.h" 103 104// For C++, add `using namespace cpu_features;` 105static const ArmFeatures features = GetArmInfo().features; 106static const bool has_aes_and_neon = features.aes && features.neon; 107 108// use has_aes_and_neon. 109``` 110 111This is a good approach to take if you're checking for combinations of features 112when using a compiler that is slow to extract individual bits from bit-packed 113structures. 114 115### Checking compile time flags 116 117The following code determines whether the compiler was told to use the AVX 118instruction set (e.g., `g++ -mavx`) and sets `has_avx` accordingly. 119 120```c 121#include <stdbool.h> 122#include "cpuinfo_x86.h" 123 124// For C++, add `using namespace cpu_features;` 125static const X86Features features = GetX86Info().features; 126static const bool has_avx = CPU_FEATURES_COMPILED_X86_AVX || features.avx; 127 128// use has_avx. 129``` 130 131`CPU_FEATURES_COMPILED_X86_AVX` is set to 1 if the compiler was instructed to 132use AVX and 0 otherwise, combining compile time and runtime knowledge. 133 134### Rejecting poor hardware implementations based on microarchitecture 135 136On x86, the first incarnation of a feature in a microarchitecture might not be 137the most efficient (e.g. AVX on Sandy Bridge). We provide a function to retrieve 138the underlying microarchitecture so you can decide whether to use it. 139 140Below, `has_fast_avx` is set to 1 if the CPU supports the AVX instruction 141set—but only if it's not Sandy Bridge. 142 143```c 144#include <stdbool.h> 145#include "cpuinfo_x86.h" 146 147// For C++, add `using namespace cpu_features;` 148static const X86Info info = GetX86Info(); 149static const X86Microarchitecture uarch = GetX86Microarchitecture(&info); 150static const bool has_fast_avx = info.features.avx && uarch != INTEL_SNB; 151 152// use has_fast_avx. 153``` 154 155This feature is currently available only for x86 microarchitectures. 156 157<a name="usagesample"></a> 158### Running sample code 159 160Building `cpu_features` (check [quickstart](#quickstart) below) brings a small executable to test the library. 161 162```shell 163 % ./build/list_cpu_features 164arch : x86 165brand : Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz 166family : 6 (0x06) 167model : 45 (0x2D) 168stepping : 7 (0x07) 169uarch : INTEL_SNB 170flags : aes,avx,cx16,smx,sse4_1,sse4_2,ssse3 171``` 172 173```shell 174% ./build/list_cpu_features --json 175{"arch":"x86","brand":" Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz","family":6,"model":45,"stepping":7,"uarch":"INTEL_SNB","flags":["aes","avx","cx16","smx","sse4_1","sse4_2","ssse3"]} 176``` 177 178<a name="support"></a> 179## What's supported 180 181| | x86³ | AArch64 | ARM | MIPS⁴ | POWER | RISCV | s390x | 182|---------|:----:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:| 183| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ | 184| FreeBSD | yes² | not yet | not yet | not yet | not yet | N/A | not yet | 185| MacOs | yes² | not yet | N/A | N/A | no | N/A | no | 186| Windows | yes² | not yet | not yet | N/A | N/A | N/A | N/A | 187| Android | yes² | yes¹ | yes¹ | yes¹ | N/A | N/A | N/A | 188| iOS | N/A | not yet | not yet | N/A | N/A | N/A | N/A | 189 1901. **Features revealed from Linux.** We gather data from several sources 191 depending on availability: 192 + from glibc's 193 [getauxval](https://www.gnu.org/software/libc/manual/html_node/Auxiliary-Vector.html) 194 + by parsing `/proc/self/auxv` 195 + by parsing `/proc/cpuinfo` 1962. **Features revealed from CPU.** features are retrieved by using the `cpuid` 197 instruction. 1983. **Microarchitecture detection.** On x86 some features are not always 199 implemented efficiently in hardware (e.g. AVX on Sandybridge). Exposing the 200 microarchitecture allows the client to reject particular microarchitectures. 2014. All flavors of Mips are supported, little and big endian as well as 32/64 202 bits. 203 204<a name="ndk"></a> 205## Android NDK's drop in replacement 206 207[cpu_features](https://github.com/google/cpu_features) is now officially 208supporting Android and offers a drop in replacement of for the NDK's [cpu-features.h](https://android.googlesource.com/platform/ndk/+/main/sources/android/cpufeatures/cpu-features.h) 209, see [ndk_compat](ndk_compat) folder for details. 210 211<a name="license"></a> 212## License 213 214The cpu_features library is licensed under the terms of the Apache license. 215See [LICENSE](LICENSE) for more information. 216 217<a name="cmake"></a> 218## Build with CMake 219 220Please check the [CMake build instructions](cmake/README.md). 221 222<a name="quickstart"></a> 223### Quickstart 224 225- Run `list_cpu_features` 226 ```sh 227 cmake -S. -Bbuild -DBUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=Release 228 cmake --build build --config Release -j 229 ./build/list_cpu_features --json 230 ``` 231 232 _Note_: Use `--target ALL_BUILD` on the second line for `Visual Studio` and `XCode`. 233 234- run tests 235 ```sh 236 cmake -S. -Bbuild -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Debug 237 cmake --build build --config Debug -j 238 cmake --build build --config Debug --target test 239 ``` 240 241 _Note_: Use `--target RUN_TESTS` on the last line for `Visual Studio` and `--target RUN_TEST` for `XCode`. 242 243 244- install `cpu_features` 245 ```sh 246 cmake --build build --config Release --target install -v 247 ``` 248 249 _Note_: Use `--target INSTALL` for `Visual Studio`. 250 251 _Note_: When using `Makefile` or `XCode` generator, you can use 252 [`DESTDIR`](https://www.gnu.org/software/make/manual/html_node/DESTDIR.html) 253 to install on a local repository.<br> 254 e.g. 255 ```sh 256 cmake --build build --config Release --target install -v -- DESTDIR=install 257 ``` 258 259<a name="bindings"></a> 260## Community bindings 261 262Links provided here are not affiliated with Google but are kindly provided by the OSS Community. 263 264 - .Net 265 - https://github.com/toor1245/cpu_features.NET 266 - Python 267 - https://github.com/Narasimha1997/py_cpu 268 - Java 269 - https://github.com/aecsocket/cpu-features-java 270 271 272_Send PR to showcase your wrapper here_ 273