Simd<T, N>
- Rust course
- Expert
- Lesson 20/46
- 4 min
Use the Simd<T, N> vector type.
Simd<T, N>
The basic type in std::simd is Simd<T, N>: element type T and lane count N (a const generic). f32x4 is in fact an alias for Simd<f32, 4>. Operators (+, *, -) are defined lane-wise:
use std::simd::Simd;
let a: Simd<f32, 8> = Simd::splat(1.0); // all lanes 1.0
let b = Simd::<f32, 8>::splat(2.0);
let c = a + b; // 8 lanes of 3.0The right lane count depends on the processor: SSE is 128 bits (4×f32), AVX2 256 bits (8×f32), AVX-512 512 bits (16×f32).
Your own lane type
We can imitate the same interface in stable Rust with const generics and the Add trait:
#[derive(Clone, Copy)]
struct Seritler<const N: usize>([f32; N]);
impl<const N: usize> Seritler<N> {
fn yay(x: f32) -> Self { Seritler([x; N]) }
}
impl<const N: usize> std::ops::Add for Seritler<N> {
type Output = Self;
fn add(self, o: Self) -> Self {
Seritler(std::array::from_fn(|i| self.0[i] + o.0[i]))
}
}Having the lane count in the type prevents accidentally adding vectors of different widths at compile time.
Practice Eight lanes
Write the Seritler<const N: usize> type above with yay and Add. Print the lane count of Seritler::<8>::yay(1.0) + Seritler::<8>::yay(2.0) and the sum of its lanes, separated by a space.
Starter code
fn main() {
// buraya yaz
}Sample solution
#[derive(Clone, Copy)]
struct Seritler<const N: usize>([f32; N]);
impl<const N: usize> Seritler<N> {
fn yay(x: f32) -> Self {
Seritler([x; N])
}
}
impl<const N: usize> std::ops::Add for Seritler<N> {
type Output = Self;
fn add(self, o: Self) -> Self {
Seritler(std::array::from_fn(|i| self.0[i] + o.0[i]))
}
}
fn main() {
let c = Seritler::<8>::yay(1.0) + Seritler::<8>::yay(2.0);
let toplam: f32 = c.0.iter().sum();
println!("{} {}", c.0.len(), toplam);
}Expected output
8 24
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 What does <code>Simd::splat(1.0)</code> produce?
- A single-element vector
- An empty vector
- The bits of 1.0
- A vector with all lanes 1.0 Correct answer
Explanation: splat "spreads" a value over all lanes; it's used in operations like multiplying by a constant.
2 Addition operator
impl<const N: usize> std::ops::____ for Seritler<N> {
type Output = Self;
fn add(self, o: Self) -> Self { .. }
}
impl<const N: usize> std::ops::Add for Seritler<N> {
type Output = Self;
fn add(self, o: Self) -> Self { .. }
}
Explanation: std::ops::Add defines the + operator.
3 Width and lane count (f32)
| Term | Meaning |
|---|---|
SSE (128 bit) |
4 |
AVX2 (256 bit) |
8 |
AVX-512 (512 bit) |
16 |
NEON (128 bit) |
4 lanes (ARM) |