Write a one-dimensional kernel once in Zig. Gompute specializes the whole abstraction at compile time — the backend is part of the type, and the CPU path compiles down to the loop you would have written by hand.
// src/kernels.zig
const g = @import("gompute");
pub const Params = struct { scale: f32 };
fn scaleRelu(x: f32, p: Params) f32 {
const y = x * p.scale;
return if (y > 0) y else 0;
}
pub const scale_relu = g.map("scale_relu", f32, Params, scaleRelu, .{});
comptime { g.exportKernels(@This()); }
// The backend is part of the type. This one is a direct inlined CPU loop.
var kernel = try g.Kernel(kernels.scale_relu, .cpu).init(0);
defer kernel.deinit();
try kernel.run(&data, .{ .scale = 2 });
Change .cpu to .cuda or .hip without touching the
call site. Or use AutoKernel to probe at run time and fall back.
The CPU backend monomorphizes to the hand-written loop. Enforced, not claimed: the build compares the emitted assembly and fails on a diff.
Your kernel file is compiled once for the host and once per GPU target. Address spaces and thread indexing stay inside the generated entry point.
Plain Zig structs become extern boundary types at compile time.
Anything without a stable representation is a compile error naming the field.
Fused expands an inline for, keeping intermediates in
registers — one kernel launch, no intermediate buffer.
g.math gives you exp, log, sin,
tanh and friends on NVPTX and AMDGCN, where the builtins simply
do not compile.
Hand-written CUDA/HIP kernels ride the same artifact pipeline via
RawKernel, for shared memory, barriers and custom ABIs.
Install, define a kernel, add one build call, pick a backend.
Pinning the device arch, multiple kernel roots, CI and Docker.
Every operation, every error, the ABI rules, and device math accuracy.
Buffer reuse, fusion, vectorized CPU kernels, raw kernels, custom ABIs.
The layer under Kernel: modules, buffers, streams, launching by hand.
What each error means and what to change, symptom first.
zig fetch --save git+https://github.com/OmarSiwy/Gompute.git
Linux and macOS. The CUDA and HIP backends need
linkSystemLibrary("c", .{}) on your executable — the drivers are
dlopen'd, and without libc Zig cannot resolve symbols out of them.