Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Detect CPU features with single-file

License

NotificationsYou must be signed in to change notification settings

nihui/ruapu

Repository files navigation

GitHub LicenseGitHub Actions Workflow Status

Detect CPU ISA features with single-file

CPU✅ x86, x86-64
✅ arm, aarch64
✅ mips
✅ powerpc
✅ s390x
✅ loongarch
✅ risc-v
✅ openrisc
#defineRUAPU_IMPLEMENTATION#include"ruapu.h"intmain(){// initialize ruapu onceruapu_init();// now, tell me if this cpu has avx2inthas_avx2=ruapu_supports("avx2");// loop all supported featuresconstchar*const*supported=ruapu_rua();while (*supported)    {fprintf(stderr,"%s\n",*supported);supported++;    }return0;}
OS✅ Windows
✅ Linux
✅ macOS
✅ Android
✅ iOS
✅ FreeBSD
✅ NetBSD
✅ OpenBSD
✅ DragonflyBSD
✅ Solaris
✅ SyterKit
Compiler✅ GCC
✅ Clang
✅ MSVC
✅ MinGW

Best practice for usingruapu.h in multiple compilation units

  1. Create oneruapu.c for your project
  2. ruapu.c isONLY#define RUAPU_IMPLEMENTATION and#include "ruapu.h"
  3. Other sources#include "ruapu.h" butNO#define RUAPU_IMPLEMENTATION

Features

  • DetectCPU ISA with single-file   sse2,avx,avx512f,neon, etc.
  • Detectvendor extended ISA    appleamx, risc-v vendor ISA, etc.
  • Detectricher ISA on Windows ARM  IsProcessorFeaturePresent() returns little ISA information
  • Detectx86-avx512 on macOS correctlymacOS hides it incpuid
  • Detectnew CPU's ISA on old systemsthey are usually not exposed inauxv orMISA
  • DetectCPU hidden ISA       fma4 on zen1, ISA in hypervisor, etc.

Supported ISA (more is comming ... :)

CPUISA
x86mmxssesse2sse3ssse3sse41sse42sse4axopavxf16cfmafma4avx2avx512favx512bwavx512cdavx512dqavx512vlavx512vnniavx512bf16avx512ifmaavx512vbmiavx512vbmi2avx512fp16avx512eravx5124fmapsavx5124vnniwavxvnniavxvnniint8avxvnniint16avxifmaavxneconvertamxfp16amxbf16amxint8amxtilebmi1bmi2gfniaesnivaessha1sha256sha512sm3sm4rdrandrdseedtsx
armhalfedspneonvfpv4idiv
aarch64neonvfpv4lsecpuidasimdrdmasimdhpasimddpasimdfhmbf16i8mmfrintjscvtfcmamtemte2svesve2svebf16svei8mmsvef32mmsvef64mmsmesmef16f16smef64f64smei64i64pmullcrc32aessha1sha2sha3sha512sm3sm4svepmullsvebitpermsveaessvesha3svesm4amx
mipsmsammisxasxmsa2crypto
powerpcvsx
s390xzvector
loongarchlsxlasx
risc-vimafdcvzbazbbzbczbszbkbzbkczbkxzcbzfazfbfminzfhzfhminzicbopzicondzicsrzifenceizihintpausezmmulzvbbzvbczvfhzvfhminzvfbfminzvfbfwmazvkbzvl32bzvl64bzvl128bzvl256bzvl512bzvl1024bxtheadbaxtheadbbxtheadbsxtheadcondmovxtheadfmemidxxtheadfmvxtheadmacxtheadmemidxxtheadmempairxtheadsyncxtheadvectorxtheadvdotspacemitvmadotspacemitvmadotnspacemitvfmadot
openriscorbis32orbis64orfpx32orfpx64orvdx64

Let's ruapu

ruapu with C

Compile ruapu test program

# GCC / MinGWgcc main.c -o ruapu
# Clangclang main.c -o ruapu
# MSVCcl.exe /Fe: ruapu.exe main.c

Run ruapu in command line

./ruapummx = 1sse = 1sse2 = 1sse3 = 1ssse3 = 1sse41 = 1sse42 = 1sse4a = 1xop = 0... more lines omitted ...

ruapu with Python

Compile and install ruapu library

# from pypipip3 install ruapu
# from source codepip3 install ./python

Use ruapu in python

importruapuruapu.supports("avx2")# Trueruapu.supports(isa="avx2")# Trueruapu.rua()#(mmx', 'sse', 'sse2', 'sse3', 'ssse3', 'sse41', 'sse42', 'avx', 'f16c', 'fma', 'avx2')

ruapu with Rust

Compile ruapu library

# from source codecd rustcargo build --release

Use ruapu in Rust

externcrate ruapu;fnmain(){println!("supports neon: {}", ruapu::supports("neon").unwrap());println!("supports avx2: {}", ruapu::supports("avx2").unwrap());println!("rua: {:?}", ruapu::rua());}

ruapu with Lua

Compile ruapu library

# from source codecd lua# lua binding has been tested on Lua 5.2~5.4luarocks make

Use ruapu in Lua

ruapu=require"ruapu";print(ruapu.supports("mmx"));for_,extinipairs(ruapu.rua())doprint(ext);end

ruapu with Erlang

Compile ruapu library

% add this to deps list% in your rebar.config{ruapu,"0.1.0"}

Use ruapu in Erlangrebar3 shell

ruapu:rua().{ok,["neon","vfpv4","asimdrdm","asimdhp","asimddp","asimdfhm","bf16","i8mm","pmull","crc32","aes","sha1","sha2","sha3","sha512","amx"]}>ruapu:supports("neon").true>ruapu:supports(neon).true>ruapu:supports(<<"neon">>).true>ruapu:supports("avx2").false>ruapu:supports(avx2).false>ruapu:supports(<<"avx2">>).false

ruapu with Fortran

Compile ruapu library

# from source codecd fortrancmake -B buildcmake --build build

Use ruapu in Fortran

program main    use ruapu, only: ruapu_init, ruapu_supports, ruapu_ruaimplicit nonecharacter(len=:), allocatable:: isa_supported(:)integer:: icall ruapu_init()print*,"supports sse:", ruapu_supports("sse")print*,"supports neon:", ruapu_supports("neon")    isa_supported= ruapu_rua()do i=1,size(isa_supported)print*,trim(isa_supported(i))end doend program main

ruapu with Golang

Compile ruapu library

cd gogo build -o ruapu-go

Use ruapu in Golang

package mainimport ("fmt""ruapu-go/ruapu""strconv")funcmain() {ruapu.Init()avx2Status:=ruapu.Supports("avx2")fmt.Println("avx2:"+strconv.Itoa(avx2Status))rua:=ruapu.Rua()fmt.Println(rua)}

ruapu with Haskell

Add ruapu library to your project

haskell/Ruapu.hs,haskell/ruapu.c andruapu.h should be copied in yourproject.

Use ruapu in Haskell

importRuapu-- Ruapu.rua :: IO [String]-- Ruapu.supports :: String -> IO Boolmain=doRuapu.initRuapu.supports"mmx">>=putStrLn.showRuapu.rua>>=sequence_.mapputStrLn

ruapu with Vlang

Compile ruapu library

cd vlangv.

Use ruapu in Vlang

modulemainimportruapufnmain() {ruapu.ruapu_init()mutavx2_status:= ruapu.ruapu_supports('avx2')ifavx2_status {println('avx2: '+avx2_status.str())    }println(ruapu.ruapu_rua())}

ruapu with Pascal

Compile ruapu library

cd pascalsudo apt install fpccmake.makefpc ruapu.lpr

Use ruapu in Pascal

program ruapu;uses ruapu_pascal;var  has_avx2: integer;  supported: PPAnsiChar;begin// initialize ruapu once  ruapu_init();// now, tell me if this cpu has avx2  has_avx2 := ruapu_supports('avx2');// loop all supported features  supported := ruapu_rua();while supported^ <>nildobegin      writeln(supported^);      inc(supported);end;  readln();end.

ruapu with Java

Compile ruapu library and example

./gradlew build

Run example

java -cp \    ./build/libs/ruapu-1.0-SNAPSHOT.jar \    ./Example.java

Use ruapu in Java

importruapu.Ruapu;importjava.util.*;classExample {publicstaticvoidmain(Stringargs[]) {Ruapuruapu =newRuapu();System.out.println("avx: " +ruapu.supports("avx"));// avx: 1System.out.println(Arrays.toString(ruapu.rua()));// [mmx, sse, sse2, sse3, ssse3, sse41, sse42, avx, f16c, fma, avx2]    }}

ruapu with cangjie

Compile ruapu library

cd cangjiecd c-srccmake.make

run example

cd cangjiecjpm run

or compile example

cd cangjiecjpm build./target/release/bin/main
Use ruapu in cangjie
import ruapu.*main(): Int64{ruapu_init()letneon_supported=ruapu_supports("neon")println("supports neon: ${neon_supported}")letd=ruapu_rua()    for(i in d){println(i)}return0}

ruapu with Dart

Compile ruapu library

cd dartbash build.sh
Use ruapu in dart
voidmain() {var libraryPath=  path.join(Directory.current.path,'build','libruapu.so');if (Platform.isMacOS) {    libraryPath=        path.join(Directory.current.path,'build','libruapu.dylib');  }if (Platform.isWindows) {    libraryPath= path.join(Directory.current.path,'build','Debug','ruapu.dll');  }Ruapu ruapu=Ruapu(libraryPath);  ruapu.init();List<String> isas= ruapu.rua();print("This CPU Support:");for (String isain isas) {print(isa);  }print("=================");String isaToCheck='aes';bool isSupported= ruapu.supports(isaToCheck);print('Does the system support $isaToCheck? $isSupported');}
Github-hosted runner result (Linux)
mmx = 1sse = 1sse2 = 1sse3 = 1ssse3 = 1sse41 = 1sse42 = 1sse4a = 1xop = 0avx = 1f16c = 1fma = 1avx2 = 1avx512f = 0avx512bw = 0avx512cd = 0avx512dq = 0avx512vl = 0avx512vnni = 0avx512bf16 = 0avx512ifma = 0avx512vbmi = 0avx512vbmi2 = 0avx512fp16 = 0avx512er = 0avx5124fmaps = 0avx5124vnniw = 0avxvnni = 0avxvnniint8 = 0avxifma = 0amxfp16 = 0amxbf16 = 0amxint8 = 0amxtile = 0
Github-hosted runner result (macOS)
mmx = 1sse = 1sse2 = 1sse3 = 1ssse3 = 1sse41 = 1sse42 = 1sse4a = 0xop = 0avx = 1f16c = 1fma = 1avx2 = 1avx512f = 0avx512bw = 0avx512cd = 0avx512dq = 0avx512vl = 0avx512vnni = 0avx512bf16 = 0avx512ifma = 0avx512vbmi = 0avx512vbmi2 = 0avx512fp16 = 0avx512er = 0avx5124fmaps = 0avx5124vnniw = 0avxvnni = 0avxvnniint8 = 0avxifma = 0amxfp16 = 0amxbf16 = 0amxint8 = 0amxtile = 0
Github-hosted runner result (macOS M1)
neon = 1vfpv4 = 1cpuid = 0asimdhp = 1asimddp = 1asimdfhm = 1bf16 = 0i8mm = 0sve = 0sve2 = 0svebf16 = 0svei8mm = 0svef32mm = 0
Github-hosted runner result (Windows)
mmx = 1sse = 1sse2 = 1sse3 = 1ssse3 = 1sse41 = 1sse42 = 1sse4a = 1xop = 0avx = 1f16c = 1fma = 1avx2 = 1avx512f = 0avx512bw = 0avx512cd = 0avx512dq = 0avx512vl = 0avx512vnni = 0avx512bf16 = 0avx512ifma = 0avx512vbmi = 0avx512vbmi2 = 0avx512fp16 = 0avx512er = 0avx5124fmaps = 0avx5124vnniw = 0avxvnni = 0avxvnniint8 = 0avxifma = 0amxfp16 = 0amxbf16 = 0amxint8 = 0amxtile = 0
FreeBSD/NetBSD/OpenBSD VM result (x86_64)
mmx = 1sse = 1sse2 = 1sse3 = 1ssse3 = 1sse41 = 1sse42 = 1sse4a = 1xop = 0avx = 1f16c = 1fma = 1fma4 = 0avx2 = 1avx512f = 0avx512bw = 0avx512cd = 0avx512dq = 0avx512vl = 0avx512vnni = 0avx512bf16 = 0avx512ifma = 0avx512vbmi = 0avx512vbmi2 = 0avx512fp16 = 0avx512er = 0avx5124fmaps = 0avx5124vnniw = 0avxvnni = 0avxvnniint8 = 0avxifma = 0amxfp16 = 0amxbf16 = 0amxint8 = 0amxtile = 0

Techniques inside ruapu

ruapu is implemented in C language to ensure the widest possible portability.

ruapu determines whether the CPU supports certain instruction sets by trying to execute instructions and detecting whether anIllegal Instruction exception occurs. ruapu does not rely on the cpuid instructions and registers related to the CPU architecture, nor does it rely on theMISA information and system calls of the operating system. This can help us get more detailed CPU ISA information.

FAQ

Why is the project named ruapu

 ruapu is the abbreviation of rua-cpu, which means using various extended instructions to harass and amuse the CPU (rua!). Based on whether the CPU reacts violently (throws an illegal instruction exception), it is inferred whether the CPU supports a certain extended instruction set.

Why is ruapu API designed like this

 We consider gcc builtin functions to be good practice, saying__builtin_cpu_init() and__builtin_cpu_supports(). ruapu refers to this design, which can be a 1:1 replacement for gcc functions, and supports more operating systems and compilers, giving it better portability.

Why does SIGILL occur when executing in debugger or simulator, such asgdb,lldb,qemu-user,sde etc.

 Because debuggers and simulators capture the signal and stop the ruapu signal handler function by default, we can continue execution at this time, or configure it specifically, such ashandle SIGILL nostop in gdb. ruapu technically cannot prevent programs from stopping in debuggers and emulators

How to add detection capabilities for new instructions to ruapu

Assume that the new extended instruction set is namedrua

  1. AddRUAPU_INSTCODE(rua, rua-inst-hex) // rua r0,r0 andRUAPU_ISAENTRY(rua) inruapu.h
  2. AddPRINT_ISA_SUPPORT(rua) inmain.c to print the detection result
  3. Add entries aboutrua in README.md
  4. Create a pull request!

https://godbolt.org/ is a good helper to view the compiled binary code of instructions.

Repos that use ruapu

  • ncnnHigh-performance neural network inference framework
  • libllmEfficient inference of large language models

Credits

Contribution behavior

License

MIT License


[8]ページ先頭

©2009-2025 Movatter.jp