Finch/examples/simd.fch
Claude 0bf66740df
Compiler and docs on every system: macOS Intel in CI, releases made by CI, docs for vectors and --cpu
- CI: macOS on Apple Silicon and Intel (macos-15, macos-15-intel); a tag v* attaches every package
  (Linux x64/ARM64, macOS ARM64/x64, Windows x64, the VS Code extension) to its release
- vectors: fma is llvm.fmuladd (llvm.fma was a libm call per lane without FMA hardware: 3.5x slower)
- examples/simd.fch: a dot product eight at a time, timed against the plain loop
- README and the English guides: installing on Linux, macOS and Windows; vectors (SIMD); --cpu;
  -g is DWARF on Windows too (lldb from llvm-mingw); no more mention of the C++ compiler
- comments left from the C++ compiler (src/target.cpp, src/codegen.cpp, "never frees") brought up to date

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Psc42moPLwP43Cmb9oZqSR
2026-11-01 13:57:28 +00:00

69 lines
1.7 KiB
Text

// Vectors (SIMD): eight f32 at once instead of one.
//
// finch run examples/simd.fch runs on any x86-64 or ARM64 processor
// finch run examples/simd.fch --cpu native uses all of this one's instructions (AVX2, AVX-512, NEON)
import time
// one number at a time
fn dot_plain([]f32 a, []f32 b) -> f32 {
f32 total = 0.0
for i in 0..a.len {
total += a[i] * b[i]
}
return total
}
// eight at a time: f32x8(list, i) takes list[i] ... list[i+7], fma multiplies and adds in one step
fn dot_simd([]f32 a, []f32 b) -> f32 {
acc := f32x8(0.0)
i := 0
while i + 8 <= a.len {
acc = f32x8(a, i).fma(f32x8(b, i), acc)
i += 8
}
total := acc.sum()
while i < a.len { // the few that are left
total += a[i] * b[i]
i += 1
}
return total
}
// brighten every color: the same work on every lane, with min keeping it below 1
fn brighten([]f32 pixels, f32 amount) {
i := 0
while i + 8 <= pixels.len {
v := min(f32x8(pixels, i) * (1.0 + amount), 1.0)
v.store(pixels, i)
i += 8
}
}
fn main() {
[]f32 a
[]f32 b
for i in 0..4_000_000 {
a.push(f32(i % 100) / 100.0)
b.push(0.5)
}
start := time.millis()
x := 0.0
for round in 0..20 {
x = float(dot_plain(a, b))
}
plain := time.millis() - start
start = time.millis()
y := 0.0
for round in 0..20 {
y = float(dot_simd(a, b))
}
simd := time.millis() - start
print("one at a time: ", str(x, 1), "in", plain, "ms")
print("eight at a time:", str(y, 1), "in", simd, "ms")
brighten(a, 0.5)
print("brightened:", a[10], a[90], a.len)
}