Live data from Hacker News

FFmpeg School of Assembly Language

github.com

171–180 of 226 posts

Re: FFmpeg School of Assembly Language

#171

Earlier quoted context omitted.

What does Zig offer in the way of builtin SIMD support, beyond overloads for trivial arithmetic operations? 90% of the utility of SIMD is outside of those types of simple operations. I like Zig, but my understanding is you have to reach for CPU specific builtins for the vast majority of cases, just like in C/C++. GCC and Clang support the vector_size attribute and overloaded arithmetic operators on those "vectorized"…

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 platform-specific SIMD code is given the progress in portable abstractions. Unless you need an exotic instruction that does not translate across architectures and/or common patterns nicely, there is little reason to have a bespoke platform-specific path.

Re: FFmpeg School of Assembly Language

#172
post #148

Earlier quoted context omitted.

You're looking for the tiniest blocks of code that are run an exceptional number of times. For instance, I used to work on graphics renderers. You'd find the bit that was called the most (writing lines of pixels to the screen) and try to jiggle the order of the instructions to decrease the number of cycles used to move X bits from system RAM to graphics RAM. When I was doing it, branching (usually checking an exit co…

Don’t modern or even just not ancient cpus use branch prediction to work past a check knowing that the vast majority of the time the check yields the same result?

Branch prediction is great for predictable branches, which is often what you have, or a good approximation to it. I forget the exact criteria, but even quite old chips could learn, e.g., all repeating patterns of length up to 4, most repeating patterns of length up to 8 and fixed-length loop patterns (n YESes followed by 1 NO) of any length.

Quite often, though, you don't have predictable branches, and then you'll pay half the misprediction cost each time on average. If you're really unlucky, you could hit inputs where the branch predictor gets it wrong more than 50% of the time.

Re: FFmpeg School of Assembly Language

#173

Earlier 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.

Doesn’t this just make it harder to maintain ports to other architectures though?

Yes, but on projects like that, ease of maintenance is a secondary priority when compared to performance or throughput.

Re: FFmpeg School of Assembly Language

#174
post #62

I personally don't think there's much value in writing assembly (vs using intrinsics), but it's been really helpful to read it. I have often used Compiler Explorer ( https://godbolt.org/ ) to look at the assembly generated and understand optimizations that compilers perform when optimizing for performance.

Your commented is directly contradicted by the article. > To make multimedia processing fast. It’s very common to get a 10x or more speed improvement from writing assembly code, which is especially important when wanting to play videos in real time without stuttering.

And how often are you doing multimedia processing?

Re: FFmpeg School of Assembly Language

#175

Earlier 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.

Doesn’t this just make it harder to maintain ports to other architectures though?

SIMD instructions are already architecture dependent

Re: FFmpeg School of Assembly Language

#176
post #32
post #31

Earlier quoted context omitted.

Have a look an their code, it is obvious. Often you have to figure out what actually the macros does, and I remember it was not that straight forward. And the macro language is specific to nasm. What to do: unroll the macros and/or use a little abstraction using a simple common macro preprocessor, aka not tied to the assembler. And I am just doing exactly that: my x86_64 assembly code does assemble with fasm/nasm/gas…

there is nothing wrong with depending on nasm

Yes, it is since you can with a little C preprocessor abstraction assemble with fasm/gas/nasm.

Re: FFmpeg School of Assembly Language

#177

Earlier 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…

Exactly!

Re: FFmpeg School of Assembly Language

#178

Another 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…

What does Zig offer in the way of builtin SIMD support, beyond overloads for trivial arithmetic operations? 90% of the utility of SIMD is outside of those types of simple operations. I like Zig, but my understanding is you have to reach for CPU specific builtins for the vast majority of cases, just like in C/C++. GCC and Clang support the vector_size attribute and overloaded arithmetic operators on those "vectorized"…

Zig ships LLVM's internal generic SIMD stuff, which is fairly common for newish systems languages. If you want dynamic shuffles or even moderately exotic things like maddubs or aesenc then you need to use LLVM intrinsics for specific instructions or asm.

Re: FFmpeg School of Assembly Language

#179

I 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…

I have no idea how to get the compiler to generate wider-than-16 pshufb in the general case, for example, and for the 16-wide case, writing the actual definition of pshufb prevents you from getting pshufb while writing a version with UB gets you pshufb.

Re: FFmpeg School of Assembly Language

#180

I 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…

We did something slightly similar - for the very few isolated things it makes sense (e.g. image up/download and conversions in the gpu driver that weren't supported/large enough to be worth firing off a gpu job to complete), they were initially written in C and used the compiler annotations to specify things like the alignment or allowed pointer aliasing in order to make it generate the code wanted. GCC and Clang both support some vector extensions, that allow somewhat portable implementations of things like scatter-gather, or shuffling things around or masking elements in a single register that's hard to specify clearly enough so that it's both readable for humans and will always generate the expected code between compiler versions in "plain" C.

But due to needing to support other compilers and platforms we actually ended up importing the generated asm from those source files in the actual build.

Post reply on HN