Live data from Hacker News

FFmpeg devs boast of another 100x leap thanks to handwritten assembly code

tomshardware.com

121–130 of 138 posts

Re: FFmpeg devs boast of another 100x leap thanks to handwritten assembly code

#121

Earlier quoted context omitted.

ISPC is a lot different from C++ compiler auto vectorization and it works extremely well. Have you tried it or not? If so where does it actually fall down? It warns you when doing slow stuff like gathers and scatters.

Is it a lot different from autovec with #pragma omp simd? I played around with ISPC a bit and it didn't seem much different.

I don't have any experience with that aspect of openmp. When you use ISPC are you using the varying and uniform keywords? You can write something that is almost C but it basically forced to vectorize.

If you both are vectorizing the same thing there might not be much difference.

If both are not vectorizing there might not be much difference, but with ISPC you can easily make sure that it does use vectorization and the best instruction set for your CPU.

Re: FFmpeg devs boast of another 100x leap thanks to handwritten assembly code

#122
post #103
post #58

Earlier quoted context omitted.

Personally I’ve never been able to beat gcc or icx autovectorization by using intrinsics; often I’m slower by a factor of 1.5-2x. Do you have any wisdom you can share about techniques or references you can point to?

You may not be able to beat the auto-vectorizer for problems which can be auto-vectorized, but you have almost certainly encountered situations which the compiler can't auto-vectorize but where you could've manually written a SIMD implementation which beats the compiler's scalar code.

Excellent point, that makes a lot of sense. You’re absolutely right that I’ve only tried problems that could be auto vectorized…

Re: FFmpeg devs boast of another 100x leap thanks to handwritten assembly code

#123

Earlier quoted context omitted.

No optimisation currently done in production compilers (that I know of) work on more than a few blocks. I haven't seen anyone claim they're not general purpose or don't scale yet, or are not reliable. Meanwhile the patch we're discussing is 2 functions, 3 blocks each. So in this context we're not talking about anything crazy.

Examples of optimization passes in llvm that reason across arbitrary numbers of blocks: - SROA - GVN - regalloc And those are just the heaviest hitters. In fact most optimization passes are capable of performing changes that impact many blocks at once.

Eh, kinda? I mean regalloc is not an optimisation pass. And SROA/GVM go through whole functions, but they don't really optimise across blocks. They do local changes only with information from previous blocks available. I meant that I don't know of anything that makes modifications across multiple blocks as one complex change. Even licm pokes one thing at a time from one block to a different one. There's no complex "let's replace this kind of cross-block pattern with a different equivalent code that changes multiple blocks at the same time".

Re: FFmpeg devs boast of another 100x leap thanks to handwritten assembly code

#124
post #14

Earlier quoted context omitted.

> you can already use a SAT solver Could you elaborate please? How would you approach this problem, using a SAT solver? All I know is that a SAT solver tells you whether a certain formula of ANDs and ORs is true. I don't know how it could be useful in this case.

Pretty much all instructions at the assembly level are sequences of AND/OR/XOR operations. SAT solvers can prove that some (shorter) sequences are equivalent to other (longer) sequences. But it takes a brute force search. IIRC, these super optimizing SAT solvers can see patterns and pick 'Multiply' instructions as part of their search. So it's more than traditional SAT. But it's still... At the end of the day.... A S…

What you're saying is true. Yes you can grind away at generating sequences of instructions, SAT solve equivalence and benchmark, but of course, you would sooner see all black holes in the observable universe evaporate before you find an instruction sequence that is both correct AND 100x faster.

Re: FFmpeg devs boast of another 100x leap thanks to handwritten assembly code

#125

Earlier quoted context omitted.

Examples of optimization passes in llvm that reason across arbitrary numbers of blocks: - SROA - GVN - regalloc And those are just the heaviest hitters. In fact most optimization passes are capable of performing changes that impact many blocks at once.

Eh, kinda? I mean regalloc is not an optimisation pass. And SROA/GVM go through whole functions, but they don't really optimise across blocks. They do local changes only with information from previous blocks available. I meant that I don't know of anything that makes modifications across multiple blocks as one complex change. Even licm pokes one thing at a time from one block to a different one. There's no complex "l…

SROA absolutely does a coordinated modification across an arbitrary number of blocks whenever it kills an alloca.

GVN has cases where it’ll also make a coordinated change across multiple blocks

And those are just two passes. I’m not mentioning the many other passes that have this property just for the sake of brevity.

Re: FFmpeg devs boast of another 100x leap thanks to handwritten assembly code

#126

Earlier quoted context omitted.

Pretty much all instructions at the assembly level are sequences of AND/OR/XOR operations. SAT solvers can prove that some (shorter) sequences are equivalent to other (longer) sequences. But it takes a brute force search. IIRC, these super optimizing SAT solvers can see patterns and pick 'Multiply' instructions as part of their search. So it's more than traditional SAT. But it's still... At the end of the day.... A S…

You're a bit naive about the complexity. Commonly longer sequences are actually faster, not just because instructions vary in their speed, but also because the presence of earlier instructions that don't feed results into later instructions still affect their performance. Different instructions consume different CPU resources and can contend for them (e.g. the CPU can stall even though all the inputs needed for a cal…

Hmm, this usually doesn't come up simply because you're usually targeting multiple different CPU generations at once, and then the details cancel each other out.

The most ffmpeg has had to do in this area is that some CPUs had very slow unaligned memory loads and some didn't.

Re: FFmpeg devs boast of another 100x leap thanks to handwritten assembly code

#127
post #32

Earlier quoted context omitted.

There are literally textbooks on computational theory, with tons of example proofs. I'm sure there are models trained on them. Why hasn't ChatGPT produced a valid P vs. NP proof yet?

I'm just countering their claim that such code is not in the training data. You're employing a logical fallacy to argue about something else.

1 book on something is not enough for LLMs to do anything useful. They aren't people.

Re: FFmpeg devs boast of another 100x leap thanks to handwritten assembly code

#128

Earlier quoted context omitted.

Sorry for the derail, but it sounds like you have a ton of experience with SIMD. Have you used ISPC, and what are your thoughts on it? I feel it's a bit ridiculous that in this day and age you have to write SIMD code by hand, as regular compilers suck at auto-vectorizing, especially as this has never been the case with GPU kernels.

Regular compilers are actually extraordinarily good at auto-vectorizing. There are a few oddities that one has to be aware of; but in my experience, if you offer a GCC or Clang compiler an opportunity to auto-vectorize, it will leap on it pretty ruthlessly. I have done a lot of work recently with auto-vectorizing code for high-performance realtime audio processing. And it's pretty extraordinary how good GCC and Clang…

I think the issue with your argument is their optimizations are brittle, due to the complex limitations needed to vectorize code, as well as subtle compiler limitations.

Their optimizations also do not necessarily carry across compilers.

If you are in gamedev, and are targeting multiple platforms, with multiple CPU architectures and compiler vendors, and your game relies on a particular function being 20x faster than the scalar version, then failing to vectorize is a blocker bug.

Imo due to this, autovectorization is more of a nice surprise than something you can rely on.

Re: FFmpeg devs boast of another 100x leap thanks to handwritten assembly code

#129
post #94

Earlier quoted context omitted.

I'm hard pressed to think of a kernel function that would benefit from auto-vectorization.

A good example is a vector addition kernel, which is simple, embarrassingly parallel, and well-suited for SIMD: void vector_add(float *a, float *b, float *c, int n) { for (int i = 0; i

OK. And which kernel function does that? Serious question.

Re: FFmpeg devs boast of another 100x leap thanks to handwritten assembly code

#130

Earlier quoted context omitted.

Regular compilers are actually extraordinarily good at auto-vectorizing. There are a few oddities that one has to be aware of; but in my experience, if you offer a GCC or Clang compiler an opportunity to auto-vectorize, it will leap on it pretty ruthlessly. I have done a lot of work recently with auto-vectorizing code for high-performance realtime audio processing. And it's pretty extraordinary how good GCC and Clang…

I think the issue with your argument is their optimizations are brittle, due to the complex limitations needed to vectorize code, as well as subtle compiler limitations. Their optimizations also do not necessarily carry across compilers. If you are in gamedev, and are targeting multiple platforms, with multiple CPU architectures and compiler vendors, and your game relies on a particular function being 20x faster than…

It boils down to: does it take longer to verify that the compiler did the right thing on each platform/architecture/processor you're interested in than it does to write hand-coded assembler which will be tightly tuned to a specific processor, and will not have proper instruction scheduling anyway, because humans just cannot do that anymore (and would have to be done all over again anyway for next year's Gen 16 intel processors that now have 7-wide instruction decoding stages instead of 5-wide instruction coding stages.

As for fragility, if it's an obvious candidate for a SIMD loop, all the compilers I have worked with so far will obviously auto-vectorize it.

What pushed me to the point of no going back: checking to see how they were doing it and finding complete models for the complete execution pipelines of literally hundreds of processor, and realizing that the reason why their code does such good instruction scheduling was because they had a full model of the execution pipeline! In both GCC and Clang sources. How long has this stuff been around for? A decade and a half? Two? The Compiler Kiddies needed SOMETHING to keep them occupied and employed for 20 years. And auto-vectorization was it. A major industry-wide initiative, specifically to address compiler auto-vectorization. AMAZING stuff. (Well. That and continuous never-ending C++ standards. But a LOT of auto-vectorization. And instruction scheduling).

Post reply on HN