Live data from Hacker News

Everyone should know SIMD

mitchellh.com

141–150 of 263 posts

Re: Everyone should know SIMD

#141
post #118

Good article! I just wouldn't start off with bold sentences as > SIMD can be simple to understand and > writing SIMD is just about as easy as a for loop and then the first example requires 12 lines to replace one line of scalar code. Be honest and say SIMD is hard but the results are worth it! (Another nitpick: if this article is for newbies, don't use SIMD-only words and concpts before explaining them. Step 5 is goo…

This is probably one of the biggest sins in technological teaching. Sure it is crucially important to take away the fear of a topic. But you don't do so by saying it is simple, you do so by showing it is simple. And it turns out sometimes you cannot show it is simple, because it is in fact very complex. But every complex topic is made up of smaller, simpler ones. Good teachers then manage to find a good order of thos…

True on all counts. Not sure why you're getting downvoted.

Re: Everyone should know SIMD

#142
post #85

It distresses me that we don’t have a language that can do a best effort parallelization of arbitrary loop like code across SIMD, multiple threads, multiple cores and GPU with a small directive. I don’t need it to be optimal, just … handy as an option! The last time I brought this up here, folks offered a bunch of options that don’t quite do this, and the best candidate was this 15 year old compiler project that is I…

> parallelization of arbitrary loop like code across SIMD, multiple threads, multiple cores and GPU

The reason we don’t have this is that it’s a holy grail, an unsolved problem, for quite fundamental reasons.

The other comment about SQL hints at why: SQL is largely declarative and has complex semantics built into the language, which allows for analysis and optimization that go beyond what’s possible for lower-level, general purpose languages, especially imperative ones.

For code in those languages, even just determining whether “arbitrary loop like code” is parallelizable is undecidable in general.

The challenge is that as you make a language expressive enough to describe arbitrary algorithms, you also make it progressively harder for a compiler to infer safe and useful parallel execution automatically.

Another big issue is that the various forms of parallelism are only similar at a very high level. They have fundamentally different execution models and constraints. Translating arbitrary imperative code to handle that essentially involves first inferring the intent of the code, then rewriting the code, including how data structures are organized, to fit the target architecture. This is far more than what ordinary compilers do.

There are also a lot of choices involved. Parallelism isn’t always free, so you’d need to make sure that the costs don’t outweigh the benefits - and you’d need to do that for many different decisions, like whether to use threads or not. Now you’d have a compiler building cost models to try to not make dumb choices - and without actually restarting and comparing alternatives, it’ll make mistakes.

In many ways, you’d be better off using an LLM for this, because that’s the level of understanding you need to have a hope of getting a good result.

That all said, you can do much better with more constrained languages or frameworks. SQL is the most successful example of that. Java’s streams and Rust’s Rayon only target multicore CPUs, but similar approaches could be used to do more. (Although you still potentially run into issues with optimal data shape across paradigms.) Languages like APL, J, and Futhark are all relevant.

The other family of solutions to this are the frameworks like Apache Spark, Apache Beam, and the ML frameworks like Pytorch. The latter lets you describe (tensor) computations at a high level, leaving the framework free to figure out how to implement them - much like with SQL.

Re: Everyone should know SIMD

#143

Earlier quoted context omitted.

> Vectors (in C++) at least aren't necessarily the best fit either I'm not sure if you use a different allocation strategy or if you're advocating allocating as much as possible up-front, but I'm curious if you have any thoughts on this: I always end up using (Rust) vectors despite looking at a bunch of slab/arena allocation libraries. Preferably I'd know how much memory I need up front, but barring that I see three…

A fourth alternative, in 64-bit systems, is to reserve a stupidly large chunk of memory up front with `mmap()` or equivalent (`malloc()` actually should work about as well). That way you guarantee that any extension will happen in place. There’s a limit to how much you can reserve, but since that limit is much higher than what you can actually use, you can make quite a few of those reservation before you run out of a…

In 32-bit systems too, but the limits are lower.

Windows is cleaner, as it lets you reserve address space and then later commit it. The Linux equivalent to reserve is probably mapping with no permissions. Overcommit can be disabled on Linux and doesn't break control flow integrity or valgrind, so I know there is a way.

Re: Everyone should know SIMD

#144
post #14

i was having a conversation with a friend recently about simd in zig (which i have recently picked up and been having a pretty good time with). i find that simd writes decently well, though there's a few weird things: - some builtins purport to work on simd vectors but actually just unpack the vectors and do their work per-element (e.g. running `@sin()` on a `@Vector(4, f32)` will unpack the vector, run `@sin()` 4 ti…

> mitchell, i know you hang around some of these comments sometimes hi im here > i noticed that in ghostty you bring in some c++ libs to do the simd heavy lifting for you. any plans to port that to zig? anything missing from the language or libs that's preventing it? No plans to port it. For others, this is referencing highway: https://github.com/google/highway The major limitation of Zig's vectors is that they're co…

Why does your website block Tor so I can't read the article?

Re: Everyone should know SIMD

#145
post #14

i was having a conversation with a friend recently about simd in zig (which i have recently picked up and been having a pretty good time with). i find that simd writes decently well, though there's a few weird things: - some builtins purport to work on simd vectors but actually just unpack the vectors and do their work per-element (e.g. running `@sin()` on a `@Vector(4, f32)` will unpack the vector, run `@sin()` 4 ti…

> some builtins purport to work on simd vectors but actually just unpack the vectors and do their work per-element (e.g. running `@sin()` on a `@Vector(4, f32)` will unpack the vector, run `@sin()` 4 times, and then pack it back into a vector). this is reasonable because there isn't really a generalizable "good way" to unroll trig functions for simd. if you really care about speed youre better off implementing to the…

Why isn't there? It's usually just a bunch of math and short branching that can be replaced with masks.

Re: Everyone should know SIMD

#146
post #107

Earlier quoted context omitted.

The problem is you need both a PL nerd and a performance nerd and while that group has some overlap so these people are not as uncommon as you’d think the task is pretty hard so you need a lot of people on it, with a bunch of funding, etc. Usually it’s just cheaper to rewrite all your code by that point and so these efforts fail

It seems like such a tempting gap though. The sort of thing you’d think in 2015 would be an obvious capability of 2026 languages!

The 2015 people didn't take into account the high stress levels in 2026. We're all struggling to pay for groceries and rent.

Re: Everyone should know SIMD

#147
The example code in this article is using Zig's portable SIMD features. Similar features are available for C/C++ (GCC/Clang extension) [0], (nightly) Rust [1] and C++26 [2].

All of these provide a similar set of features and you can use normal arithmetic operations (+, -, *, etc) for SIMD vectors. Together with templates/generics you can also write code that can deal with any vector width. These get compiled to LLVM vector types and will generally give you pretty good generated code.

This is a very good way of writing basic SIMD code and has the benefit that your code can be compiled to multiple instruction sets. I've been working on a project that can compile down to SSE2, AVX2, AVX-512 and NEON, with just a change of compiler options. Somewhat surprisingly I get the best performance by using 2x the native vector width (ie. f32x16 = 512 bits on 256 bit AVX2), which is kinda like unrolling the loop once.

There are some caveats, though. You will need to keep an eye on the generated assembly code to make sure you're on the happy path. You will inevitably need to drop down to ISA specific intrinsics every now and then (for that fast reciprocal square root with `__mm_rsqrt_ps` etc).

As an example I needed to do a gather load from an array of fp16's on AVX2, which does not do 16 bit loads. Rust's `Simd::gather_select` takes 64 bit usize as the index but AVX2 doesn't do 64 bit indices. But as long as I did all the index arithmetic in 32 bits and cast to usize at the last second, the compiler did what I wanted. But you need to kinda know what is available in the ISA to stay on the happy path. Not really an issue with arithmetic.

I'm sure that an experienced SIMD programmer can get better performance by writing intrinsics manually (say 5-20% better) but I'm already at 3-6x better than the scalar implementation I started with. And you'd have to write (and benchmark) the code for each ISA separately, meaning that you'd spend at least five times more time with it (and have 5x more code to maintain).

[0] https://gcc.gnu.org/onlinedocs/gcc-4.6.1/gcc/Vector-Extensio... [1] https://doc.rust-lang.org/nightly/std/simd/index.html [2] https://en.cppreference.com/cpp/numeric/simd

Re: Everyone should know SIMD

#148
post #133

Earlier quoted context omitted.

auto-vectorization is not nearly as good as you would hope it to be. The best SIMD optimizations likely require changing your data format from AoS to SoA.

> The best SIMD optimizations likely require changing your data format from AoS to SoA. We do have gather load instructions in SIMD instruction sets these days (AVX2 and newer), so AoS vs SoA is not nearly as important as it was once. Scatter stores are also available but only in newer CPUs.

It remains extremely important. Gather loads are much more expensive than sequential loads, for obvious reasons.

Re: Everyone should know SIMD

#149
>> you'll begin to naturally decompose every for loop into these five steps

Does zig have auto vectorisation? I'm thinking that if you write the code in a vector friendly way, then the compiler can do the boiler plate for you

https://llvm.org/docs/Vectorizers.html

https://inside.java/2025/08/16/jvmls-hotspot-auto-vectorizat...

Re: Everyone should know SIMD

#150

Earlier quoted context omitted.

It's a great talk, I just wish there was a good focused textual version of it, as it is a very long video to recommend to others. Very worth it, but a big investment. It's a great example of what I think of as vertical integration for performance. As you go through the talk you can understand why all these abstractions exist and why they have to be so generic. But when you have a specific use case, you can vertically…

Be the change you want to see. Post a transcript on your own website.

Yes, I will do that when I have time one of these years. I did mean to caveat that in my post but forgot. I mainly wanted to make the vertical integration point.
Post reply on HN