SIMD, Vectors and Inline Assembly
31.1 @Vector
const V4 = @Vector(4, f32);
const a: V4 = .{ 1, 2, 3, 4 };
const b: V4 = @splat(2.0);
const c = a * b + a; // element-wise operations
const total = @reduce(.Add, c); // horizontal reduction
const mask = a > b; // @Vector(4, bool)
const picked = @select(f32, mask, a, b);
const shuffled = @shuffle(f32, a, undefined, [4]i32{ 3, 2, 1, 0 });
const arr: [4]f32 = c; // vector ↔ array coercion
std.debug.print("{d} {any} {any}\n", .{ total, picked, arr });
_ = shuffled;
fn sumSimd(data: []const f32) f32 {
const L = std.simd.suggestVectorLength(f32) orelse 4;
var acc: @Vector(L, f32) = @splat(0);
var i: usize = 0;
while (i + L <= data.len) : (i += L) {
const chunk: @Vector(L, f32) = data[i..][0..L].*;
acc += chunk;
}
var s = @reduce(.Add, acc);
while (i < data.len) : (i += 1) s += data[i];
return s;
}31.2 Inline Assembly
Clobber syntax changed in 0.15 (struct of booleans instead of strings). Global assembly goes in comptime { asm (...); }.
fn rdtsc() u64 {
var lo: u32 = undefined;
var hi: u32 = undefined;
asm volatile ("rdtsc"
: [lo] "={eax}" (lo),
[hi] "={edx}" (hi),
);
return (@as(u64, hi) << 32) | lo;
}
fn syscall1(number: usize, arg1: usize) usize {
return asm volatile ("syscall"
: [ret] "={rax}" (-> usize),
: [number] "{rax}" (number),
[arg1] "{rdi}" (arg1),
: .{ .rcx = true, .r11 = true, .memory = true }); // 0.15 clobber syntax
}