Live data from Hacker News

Zig – SPIR-V Backend Progress

ziglang.org

31–40 of 75 posts

Re: Zig – SPIR-V Backend Progress

#31
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.

Re: Zig – SPIR-V Backend Progress

#32
post #20

I really love everything about zig except the language itself. The governance, the culture, all of it seem really cool, but reading https://ziglang.org/learn/why_zig_rust_d_cpp/ I still don't get _why_ I would use it. To an untrained eye, it seems like go, but with manual allocation. Or an imperative-only rust. Like it has some features of all the languages it competes with, but not the ones that would make me reach…

I really think the best way to describe it is an attempt to replace C. Go is only like C in that it's simple. But it's clearly not a direct C replacement. It's not a great language for writing an OS or embedded code. Rust may replace C in many contexts, but Rust is much more like C++. It adds a lot of complexity to the language and the compiler. I think it does it in a much better way than C++ so I think it is more l…

Similar thoughts as well. But also want to add Rust being a complex language is now greatly helped by AI as well.

I think there still a long way to go before the final version of Zig. I am increasingly thinking 0.17 and 0.18 won't even be close to RC. But I really like the direction that Zig is solving a lot of problems not with language features but with its tool chains. Something I thought was obvious and should have been what it is in the first place. Instead we go increasingly big and complex language.

Re: Zig – SPIR-V Backend Progress

#33
post #27
post #4

Earlier quoted context omitted.

Try reading zig code. For me its much more readable than the other languages, and does not suffer the fact go doesnt have language level errors. Local allocators are very useful and if you dont think so, perhaps you havent dwelved too deeply into systems programming or the language isnt targeted for you.

The dot syntax used everywhere really confuses me. I get its use in struct fields, or for defining anonymous structs, but what is this one for? (Some kind of module-level enum space, where .sampler and .unknown are defined previously?) const Sampler = @SpirvType(.sampler); ^ const Image = @SpirvType(.{ .image = .{ .usage = .{ .sampled = u32 }, .format = .unknown, ^ } }); Everything else about zig is quite readable, b…

"Dot" in zig is a placeholder for types that can be unambigously inferred from the surrounding expression.

So ".unknown" is a standin for "SomeEnum.unknown" or "SomeStruct.unknown", depending on what .format is.

Re: Zig – SPIR-V Backend Progress

#34
post #24

Earlier quoted context omitted.

> That said, leafing through the first chapters of "Expert C Programming" should dissuade anyone of the idea that C is a simple language. It'll leave you amazed anyone's been able to write working programs in it What footguns are present in C bit not in C++? C++ has all the footguns from C and adds multiple more. C++ is not a replacement for C, in the same way that a spacecraft is not a replacement for a Cessna.

"Correct" modern C++ eliminates whole classes of problems. You can of course still write C code, but no one would merge that in to their codebase Theyre both complicated languages in their own way :)

> "Correct" modern C++ eliminates whole classes of problems. You can of course still write C code, but no one would merge that in to their codebase

That requires the programmer to practice discipline. If someone needs something better than C, there's alternatives to C++ that don't require "Programmer needs to be disciplined".

> Theyre both complicated languages in their own way :)

No. C++ is, without doubt, the most complicated language there is. Nothing else, not Java, C#, Rust, etc comes even close.

C, OTOH, is simple enough that implementing it is practical even for students. The number of footguns are a handful.

They are severe, but not numerous. C++ has both numerous and severe footguns.

Re: Zig – SPIR-V Backend Progress

#35
post #27

Earlier quoted context omitted.

The dot syntax used everywhere really confuses me. I get its use in struct fields, or for defining anonymous structs, but what is this one for? (Some kind of module-level enum space, where .sampler and .unknown are defined previously?) const Sampler = @SpirvType(.sampler); ^ const Image = @SpirvType(.{ .image = .{ .usage = .{ .sampled = u32 }, .format = .unknown, ^ } }); Everything else about zig is quite readable, b…

"Dot" in zig is a placeholder for types that can be unambigously inferred from the surrounding expression. So ".unknown" is a standin for "SomeEnum.unknown" or "SomeStruct.unknown", depending on what .format is.

Yeah, after looking it up, it looks like it is basically only used as either field access or an 'infer operator', is that right?

I thought it was used in four completely separate ways:

· normal struct field access

· anonymous struct definition

· field definition within structs (for reasons to do with the parser)

· an extra 'infer operator' for syntactic sugar

But there's no support for anonymous structs/fields, and all structs and fields require a type somewhere for it to be inferred. Which is why this is invalid zig:

  const test = .{ .x = 0, .y = 1 };
(It would need the type to be specified in the called function definition, or inline when assigning)

Correct me if I'm wrong here! (And thank you)

Re: Zig – SPIR-V Backend Progress

#36
post #10

Side question as I am following zig only losely and do Go Programming: Zig has the feature that you can drop in your allocator from the caller. Now with 0.16 you also "bring your own IO" implementation with you. And for my understanding this looks like the pattern Go uses with its Context package, where you pass in transitive data, cancellation signals and timers to for example stop an SQL query in server B, since a…

What Zig is doing is called "capability passing". I don't know if the Zig team is aware of this field of work, or have independently arrived upon it, but that's what is achieved by passing IO, memory allocators, and other stuff around. The core idea is that you create a "capability" for any action you want to track, such as using IO, allocating memory, or in your example making cross core or cross server calls. Now t…

That looks like a convoluted way to describe dependency injection to me, what am I missing.

Re: Zig – SPIR-V Backend Progress

#37

I really love everything about zig except the language itself. The governance, the culture, all of it seem really cool, but reading https://ziglang.org/learn/why_zig_rust_d_cpp/ I still don't get _why_ I would use it. To an untrained eye, it seems like go, but with manual allocation. Or an imperative-only rust. Like it has some features of all the languages it competes with, but not the ones that would make me reach…

If you want something better than C you aren't going to reach for Go (GC) or Rust (complexity). Zig looks like a good middle ground.

Same as Odin or C3.

Re: Zig – SPIR-V Backend Progress

#38

I really love everything about zig except the language itself. The governance, the culture, all of it seem really cool, but reading https://ziglang.org/learn/why_zig_rust_d_cpp/ I still don't get _why_ I would use it. To an untrained eye, it seems like go, but with manual allocation. Or an imperative-only rust. Like it has some features of all the languages it competes with, but not the ones that would make me reach…

C is over 50 years old, but it is still more or less the lingua franca of computing. The world benefits from having "C with some improvements from 50 years of learning". The world also benefits from having featureful languages that are a huge divergence from C, but it also just needs a language that provides a thin cross-hardware abstraction over the asm layer and some conveniences over writing raw asm. We don't need…

The problem with this is imho that for a C replacement it doesn't offer enough to C programmers to switch.

If you're comfortable with C you will stick with C and benefit from it being the lingua franca, and not struggle to find support or talent.

This is true both at work or OS.

As a very talented C dev told me, I can see the point or go or Rust that would solve some of my issues, Zig while being an improvement doesn't solve any of my real pain points.

Re: Zig – SPIR-V Backend Progress

#39

Earlier quoted context omitted.

What Zig is doing is called "capability passing". I don't know if the Zig team is aware of this field of work, or have independently arrived upon it, but that's what is achieved by passing IO, memory allocators, and other stuff around. The core idea is that you create a "capability" for any action you want to track, such as using IO, allocating memory, or in your example making cross core or cross server calls. Now t…

That looks like a convoluted way to describe dependency injection to me, what am I missing.

You're right, they are related. One difference is simply lineage. Capabilities come out of the erights / security world (e.g. [0]), while dependency injection comes from the XP / agile / Martin Fowler world. More interesting is that to do capabilities correctly you need some type system extensions, namely capture checking. Essentially, this means you delimit where a program can hold a reference to a value derived from a capability. So if you have a function that allocates memory, you can say "there are no references to any allocated memory outside this function call" and hence no use-after-free bugs. It gives a form of resource management that is simpler than Rust's lifetimes. See [1] and [2]. (Technically it's a modal type system versus Rust's substructural type system.) To my mind it's an obvious thing for Zig to add.

Shameless plug. If you're interested in more on this, for a programmer's rather than academic perspective, this is going into my book [3]. I'm writing the chapter of capability passing right now.

Back to writing!

[0]: https://blog.acolyer.org/2016/02/16/capability-myths-demolis...

[1]: https://effekt-lang.org/tour/captures

[2]: https://docs.scala-lang.org/scala3/reference/experimental/cc...

[3]: https://functionalprogrammingstrategies.com/

Re: Zig – SPIR-V Backend Progress

#40

Earlier quoted context omitted.

That looks like a convoluted way to describe dependency injection to me, what am I missing.

You're right, they are related. One difference is simply lineage. Capabilities come out of the erights / security world (e.g. [0]), while dependency injection comes from the XP / agile / Martin Fowler world. More interesting is that to do capabilities correctly you need some type system extensions, namely capture checking. Essentially, this means you delimit where a program can hold a reference to a value derived fro…

So it's essentially low level dependency injection where it's not just about the interface but the system and it's resources too, right?

I will take a look at your content, these topics interest me a lot.

Post reply on HN