logoalt Hacker News

mccoybtoday at 9:18 AM1 replyview on HN

This is inspiring! At the same time, it’s not exactly clear to me how this is going to work in the long term without changes to the Zig language itself, questions below.

Assuming the goal is to be able to write compute kernels and shaders in Zig - the concerns of writing (and especially optimizing) these programs are significantly different from high-performance CPU execution.

Mojo, for instance, has seemed to solve this problem (presumably: I haven’t studied the compiler myself, but this is a claim of theirs) but the community has implied that solving this problem required semantic and compiler design decisions different from the Zig compiler, especially around memory spaces, pointers, and origins.

Further: if you open up a modern tensor / GPU compiler (Triton, XLA, logical / scheduled kernel systems like Halide or Exo, or low-level kernel compilers like Mojo) — the optimizations and analyses which are performed on GPU kernel code are significantly different than CPU code

Is the end goal to write such a pipeline into the Zig compiler?

It seems possible to do this - but I’m not sure … it seems a bit hacky, or like one has to coerce existing Zig semantics to be repurposed for a job it was not designed for in the first place?

One alternative might be to use comptime to expose a kernel builder DSL, followed by a GPU compiler pipeline implemented in Zig (a completely separate compiler). This seems straightforward and allows you to implement and gain access to the specialized semantics / optimizations that you’d need for high-performance kernels?

I could absolutely be wrong, interested in thoughts.


Replies

flohofwoetoday at 12:02 PM

Zig's SPIRV support is on the same abstraction level as GPU shading languages (GLSL, MSL, HLSL, WGSL, ...), there's nothing particularly "magic" about turning imperative source code (no matter if Zig or any other language) into a sequence of SPIRV instructions, it's not all that much different from generating x86 or ARM instructions.

The main difference to 'traditional' CPU programming is that you don't write an entire 'application' with a single main function, but instead many small-ish self-contained functions that will run 'per vertex', 'per pixel' or 'per compute invocation' on the GPU.

The Zig toolchain is only concerned about how to compile Zig code into SPIRV blobs, but not about how that code is then 'uploaded' and 'orchestrated' on the GPU, instead this is the job of APIs like Vulkan (e.g. there is no magic integration between CPU- and GPU-side code in the Zig toolchain like in the CUDA toolchain).

SPIRV's specification basically defines what features Zig needs to expose as specialized builtins or language features (e.g. things like `@SpirvType(.sampler);` or `@SpirvType(.{ .image = .{...` or `@extern(*addrspace(.constant)` map directly to SPIRV concepts (the same concepts that dedicated shading languages had to add on top of C or C++).

show 1 reply