Live data from Hacker News

Branchless Rust: Making a Filter 4x Faster by Removing an If

greyblake.com

91–100 of 124 posts

Re: Branchless Rust: Making a Filter 4x Faster by Removing an If

#91
post #75

Earlier quoted context omitted.

This isn't a necessarily true assumption. I my social circles of non native English speakers, most of us use English to talk with models.

I switch languages randomly.

What do Claude's tics look like in your other language? Do they carry over or does each language get its own weird rhetorical flourishes?

Re: Branchless Rust: Making a Filter 4x Faster by Removing an If

#93
post #86

Nice post! You can do even a bit better if you're willing to use intrinsics. In particular this kind of operation is well-suited for compress-type operations, available as a first-class operation in at least AVX512, SVE and RVV; you can also emulate them reasonably quickly on NEON and AVX2. Here's an example, building on the OP's work: pub fn filter_compress(input: &[f64], threshold: f64) -> Vec { use std::arch::x86_…

Keep in mind it's UB to be: > Executing code compiled with target features that the current thread of execution does not support I.e. calling AVX512 on Neon architecture. You need to wrap it in target attributes to even dream of it being safe.

This particular UB is not one of the subtle cases. You will almost certainly get illegal instruction signals if you mess this up.

Re: Branchless Rust: Making a Filter 4x Faster by Removing an If

#94
> The predictor is like a barista who starts making your usual order the moment you walk in. If you are a regular, this is fantastic: the coffee is ready when you reach the counter. If you order something random every day, the barista keeps pouring drinks into the sink.

I laughed out loud reading this. Interesting writeup. I wonder what kinds of tricks like this exist for computation graph compilers like JAX.

Re: Branchless Rust: Making a Filter 4x Faster by Removing an If

#95

Earlier quoted context omitted.

It was fun to read and insightful for me, not too artificial, and not too verbose. I'm glad my internal AI detector doesn't win over my curiosity to learn.

The main problem with the article is that the idea to influence backend code generation decisions via specific highlevel code constructs is mostly just mystical bullshit (some compilers do detect specific patterns - usually for bit twiddling hacks, but not on a basic level like control flow optimization). Using a highlevel language construct like "y += (x > 0) as usize;" doesn't "switch on" branchless code just becau…

PS:

> fwiw I can't shake the feeling now that the article is recycled

Ok, I remembered wrong. The article I remembered was this: https://tiki.li/blog/blqsort

HN link: https://news.ycombinator.com/item?id=48375445

It's peddling the exact same myth though.

Re: Branchless Rust: Making a Filter 4x Faster by Removing an If

#96
post #16

This problem is called stream compaction and there is a wealth of research on it. The best methods use prefix scan. They first efficiently compute the index in the output array of each element that satisfies the predicate and then they gather them in one linear operation. Also, I can tell that you are a good writer. You didn't need the LLM to "polish" your text.

If your objects are large, I can see why you would compute indices first. But why do that for floats?

Because what makes stream compaction challenging is the loop carried dependency: the location you write to in a given iteration depends on the locations you wrote to in previous iterations. By first creating a lookup table of source -> destination locations you remove the dependency. Then you can apply extremely efficient parallel methods.

Re: Branchless Rust: Making a Filter 4x Faster by Removing an If

#98

Earlier quoted context omitted.

Thank you for sharing this. How would you emulate this kind of operation on avx2?

Once you have a mask of the positions you want to compress, you can generate a shuffle index vector from that mask to place the desired elements in the low part of the vector. You can expand the mask into nibble-sized indices using pext/pdep and some magic constants, then expand those nibble-sized indices into a vector of indices to use as the shuffle indices.

Yes, that's one approach. Another reasonable approach is to get out a mask from the comparison using `vmovmskpd` and use that to look up a shuffle constant, since there are only 16 possibilities. This also works well on NEON, although I wonder there whether it'd make more sense to find the shuffle dynamically rather than loading it.

Re: Branchless Rust: Making a Filter 4x Faster by Removing an If

#99
Based on the title, I knew the issue as soon as I looked at the first table. Still, great primer for those who don't know about such CPU shenanigans, and I did appreciate the solution, since I knew high level how to solve it, but didn't come up with an actual piece of code before the author presented theirs.

I didn't know about branch prediction or pipelined CPUs back when I was profiling the code I wrote - honestly it probably would have helped.

Post reply on HN