CPUID
- Rust course
- Expert
- Lesson 29/46
- 4 min
Invoke special instructions like CPUID.
CPUID
x86's cpuid instruction gives information about the processor: the vendor name, supported instruction sets (SSE, AVX, AVX-512...). A "leaf" number is written to eax, and the result comes back in eax, ebx, ecx, edx. Instead of hand-written assembly, the standard library offers ready tools:
use std::arch::x86_64::__cpuid;
let r = unsafe { __cpuid(0) }; // leaf 0: vendor
// r.ebx, r.edx, r.ecx → "GenuineIntel" or "AuthenticAMD"
if is_x86_feature_detected!("avx2") {
// the AVX2 path
}is_x86_feature_detected! caches the result; it's ideal for picking the best implementation at runtime.
Runtime selection
Several versions of the same function are written for different instruction sets and the best one is chosen at runtime:
fn toplam(v: &[f32]) -> f32 {
#[cfg(target_arch = "x86_64")]
if is_x86_feature_detected!("avx2") {
return unsafe { toplam_avx2(v) };
}
v.iter().sum()
}
#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "avx2")]
unsafe fn toplam_avx2(v: &[f32]) -> f32 { v.iter().sum() }#[target_feature] recompiles the function with AVX2 enabled; the compiler can use wide vectors in it.
Practice Processor features
On x86-64, print the results of __cpuid(0).eax > 0 (the highest supported leaf) and is_x86_feature_detected!("sse2") separated by a space; on other architectures print true true. (Every x86-64 processor has SSE2.)
Starter code
fn main() {
// buraya yaz
}Sample solution
#[cfg(target_arch = "x86_64")]
fn islemci_bilgisi() -> (bool, bool) {
// SAFETY: cpuid her x86-64 işlemcide vardır.
let r = unsafe { std::arch::x86_64::__cpuid(0) };
(r.eax > 0, is_x86_feature_detected!("sse2"))
}
#[cfg(not(target_arch = "x86_64"))]
fn islemci_bilgisi() -> (bool, bool) {
(true, true)
}
fn main() {
let (a, b) = islemci_bilgisi();
println!("{} {}", a, b);
}Expected output
true true
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Why is writing <code>cpuid</code> by hand with <code>asm!</code> tricky?
- It's very slow
- It isn't tricky
- LLVM reserves rbx, so it can't be an operand; it must be saved and restored Correct answer
- cpuid doesn't exist
Explanation: std::arch::__cpuid handles this detail correctly; in most cases intrinsics are safer than raw assembly.
2 Feature check
if ____!("avx2") {
// AVX2'li yol
}
if is_x86_feature_detected!("avx2") {
// AVX2'li yol
}
Explanation: is_x86_feature_detected! checks at runtime whether the processor supports the feature.
3 Tool and timing
| Term | Meaning |
|---|---|
#[cfg(target_feature)] |
Compile time |
is_x86_feature_detected! |
Runtime |
__cpuid(0) |
Vendor info |
#[target_feature(enable)] |
Per-function feature |