Earlier quoted context omitted.
C compilers are still pretty bad at auto vectorization. For problems where SIMD is applicable, you can reasonably expect a 2x-16x speed up over the naive scalar implementation.
Also, if you write code with intrinsics the autovectorization can make it _worse_. eg a pattern is to write a SIMD main loop and then a scalar tail, but it can autovectorize that and mess it up.
FFmpeg School of Assembly Language
201–210 of 226 posts
Re: FFmpeg School of Assembly Language
#202Earlier quoted context omitted.
One of the fun things about dav1d is that since it’s written in assembly, they can use their own calling convention. And it can differ from method to method, so they have very few stack stores and loads compared to what a compiler will generate following normal platform calling conventions.
I'm curious why there are even function calls in time-critical code, shouldn't just about everything be inlined there? And if it's not time-critical, why are we interested in the savings from a custom calling convention?
And don't forget that any asm-optimized variant always has a C fallback for generic platforms lacking a hand-optimized variant which is also used to verify the asm-optimized variant using checkasm. This might not be linked into your binary/library (the linker eliminated it because it's never used), but the code exists nonetheless.
Re: FFmpeg School of Assembly Language
#203Another resource on the same topic: https://blogs.gnome.org/rbultje/2017/07/14/writing-x86-simd-... As I'm seeing in the comments here, the usefulness of handwritten SIMD ranges from "totally unclear" to "mission critical". I'm seeing a lot on the "totally unclear" side, but not as much on the "mission critical", so I'll talk a bit about that. FFmpeg is a pretty clear use case because of how often it is used, but I t…
I'm also in the mission-critical camp, with perhaps an interesting counterpoint. If we're focusing on small details (or drowning in incidental complexity), it can be harder to see algorithmic optimizations. Or the friction of changing huge amounts of per-platform code can prevent us from escaping a local minimum. Example: our new matmul outperforms a well-known library for LLM inference, sometimes even if it uses AMX…
It should be obvious that both are pursued independently whenever it makes sense. The idea that one should precede the other or is more important than the other is simply untrue.
Re: FFmpeg School of Assembly Language
#204Earlier quoted context omitted.
I’m also wondering what “built in” even means. Many have SIMD, Vector, Matrix, Quaternions and the like as part of the standard library, but not necessarily as their own keywords. C#/.NET, Java has SIMD by this metric.
Java's Panama Vectors are work in progress and are far from being competitive with .NET's implementation of SIMD abstractions, which is mostly on par with Zig, Swift and Mojo. You can usually port existing SIMD algorithms from C/C++/Rust to C# with few changes retaining the same performance, and it's practically impossible to do so in Java. I feel like C veterans often don't realize how unnecessarily ceremonious plat…
Re: FFmpeg School of Assembly Language
#205Earlier quoted context omitted.
One of the fun things about dav1d is that since it’s written in assembly, they can use their own calling convention. And it can differ from method to method, so they have very few stack stores and loads compared to what a compiler will generate following normal platform calling conventions.
I'm curious why there are even function calls in time-critical code, shouldn't just about everything be inlined there? And if it's not time-critical, why are we interested in the savings from a custom calling convention?
Re: FFmpeg School of Assembly Language
#206Earlier quoted context omitted.
Gstreamer is increasingly developed in Rust, and is a far saner, better documented and more flexible framework for developers than libav/ffmpeg. The pipeline/plugin based architecture is pretty neat even as an end user, I find it a lot more discoverable.
Gstreamer is a high level API that uses FFmpeg, not a FFmpeg replacement.
Because GStreamer is designed to be modular and plugin-based, all sorts of plugins exist for it (including libav plugins) but it is itself a media framework that is quite capable of replacing ffmpeg. Neither is "higher level" than the other.
Re: FFmpeg School of Assembly Language
#207I used to do quite a bit of SIMD version of critical functions, but now I rarely do -- one thing to try is isolate that code, and run it in the Most Excellent Compiler Explorer [0]. And stare at the generated code! More often than not, the auto-vectorisation now generates pretty excellent SIMD version of your function, and all you have to do is 'hint' the compiler -- for example explicitly list alignment, provide you…
Re: FFmpeg School of Assembly Language
#208Earlier quoted context omitted.
The counterpoint to this is that if you can write AVX2 assembly, that will be supported on ~99% of x86 CPUs around today (Haswell was 2013), so just that one branch covers ~80% of the desktop/laptop market.
There’s no guarantee that the fastest AVX2 assembly is equal on all CPUs, and reading https://stackoverflow.com/a/64782733 , there are differences between CPUs. So, chances are you’ll need to have more than one AVX2 assembly version of your code if you want to have the fastest code.
Re: FFmpeg School of Assembly Language
#209It doesn't mention the downsides of using assembly. The biggest of which is that your code is architecture specific, so for example you have to write different code for x86 and arm, and possibly even different code for x86_64. Unfortunately, for SIMD, there isn't really a great way to write portable code for it, at least in C. Rust is working on stabilizing a portable simd API, and zig has simd support, but I suspect…
The thing that is present in Zig and not yet stable in Rust does not include any dynamic shuffles, so these end up requiring intrinsics or asm for all sorts of things. It's a significant weakness compared to e.g. highway, eve, or simde.
Re: FFmpeg School of Assembly Language
#210Earlier quoted context omitted.
I'm also in the mission-critical camp, with perhaps an interesting counterpoint. If we're focusing on small details (or drowning in incidental complexity), it can be harder to see algorithmic optimizations. Or the friction of changing huge amounts of per-platform code can prevent us from escaping a local minimum. Example: our new matmul outperforms a well-known library for LLM inference, sometimes even if it uses AMX…
> I sure hope a broader exploration precedes micro-optimizing register allocation and calling conventions. It should be obvious that both are pursued independently whenever it makes sense. The idea that one should precede the other or is more important than the other is simply untrue.
Are you really suggesting writing a variant of a kernel, tuning it to the max, then discovering a new and different way to do it, and then discarding the first implementation? That seems like a lot of wasted effort.