The video decode stage feeding your inference model is running slow, so someone proposes a bigger GPU. Before anyone signs a purchase order, check whether the FFmpeg binary doing the decode, scale, and pixel-format conversion is even using the SIMD codepaths the Ryzen chip exposes. On AMD Ryzen this is not a settled question. “AVX-512 on” is not a single answer — it is a measured, per-target claim, because both whether the extension is present and how wide it runs vary by generation. That distinction is the whole article. A generic FFmpeg build downloaded from a package repository is compiled for a lowest-common-denominator instruction set so it runs everywhere. It will happily execute on your Ryzen box while leaving the fastest available codepath dark. Preprocessing then becomes the silent bottleneck a profiler flags — and the fix has nothing to do with the model or the GPU. Why CPU preprocessing becomes the silent bottleneck Most people reason about an inference service as “the model runs on the GPU.” That is where the parameters live, so that is where attention goes. But a video or image pipeline does real work before a single tensor reaches the accelerator: demuxing the container, decoding frames, scaling to the model’s input resolution, converting pixel formats (YUV to RGB is the common one), and often normalising. On a CPU-bound preprocessing path, that work can consume a meaningful share of end-to-end p95 latency — the part spent before the model runs. When the GPU sits idle waiting for frames, adding GPU capacity buys nothing. The accelerator was never the constraint. We see this pattern regularly: a team reports “the model is slow,” the profiler shows the GPU at 40% utilisation, and the real bottleneck is a single-threaded or SIMD-starved decode loop on the CPU. Mapping where each stage sits in the request path is the first move — the same discipline covered in our walkthrough of mapping the serving path in a machine learning architecture diagram. Until you know which stage owns the latency, every optimisation is a guess. FFmpeg is the workhorse for this stage in a large fraction of pipelines. Its decode, scale (swscale), and filter routines have hand-written SIMD implementations — SSE, AVX2, AVX-512 — selected at runtime based on what the CPU reports. That runtime dispatch is the mechanism most teams forget exists, and it is exactly where the AVX-512 question lives. Which AMD Ryzen generations expose AVX-512, and why width matters Here is the part that trips people up. AVX-512 on AMD is generation-dependent, and even where it is present, the microarchitectural width is not uniform. Zen 3 and earlier Ryzen — no AVX-512. The instructions are simply not available; FFmpeg falls back to AVX2 (256-bit) codepaths. Zen 4 (Ryzen 7000) — AVX-512 is exposed, but the vector units are physically 256 bits wide. The 512-bit instructions are handled by “double-pumping”: each 512-bit operation is split and issued over the 256-bit datapath across cycles. It still works, and it can still win, but it behaves differently from a native 512-bit unit. Zen 5 (Ryzen 9000 / desktop) — AVX-512 support with a wider datapath on parts of the lineup, closer to a native implementation. The practical consequence: an FFmpeg codepath that assumes a native 512-bit unit — as found on some Intel server parts — may not deliver the same relative speedup on a double-pumped Zen 4 core, and on Zen 3 it will not fire at all. This is why “recompile with AVX-512” is not a portable instruction. It is a hypothesis you test against the specific silicon in front of you. Per AMD’s published architecture documentation, the Zen 4 512-bit execution is delivered over 256-bit units; treat that as a hardware fact when you reason about expected gains (attribution to public specs). The reason double-pumped AVX-512 can still win on Zen 4, despite the narrow datapath, is not raw vector width — it is the encoding. AVX-512 brings more registers, masking, and denser instruction encoding, which can reduce instruction count and register pressure even when the physical lanes are 256 bits. Whether that translates into faster swscale throughput on your workload is measurable, not assumable. How do you tell whether a generic FFmpeg build is using the right codepath? This is the diagnostic that turns a hunch into a decision. You need three facts: what the CPU exposes, what the binary was built to target, and which codepath actually fires at runtime. Preprocessing-path SIMD diagnostic checklist Confirm what the CPU exposes. On Linux, grep avx512 /proc/cpuinfo (or lscpu) tells you whether AVX-512 flags are present on this Ryzen generation. Absent flags end the AVX-512 conversation immediately — it will never fire. Confirm what the binary targets. ffmpeg -buildconf shows the configure flags. A distro build compiled for a generic baseline will not have tuned for your microarchitecture; that is expected, not a bug. Confirm which codepath fires. Run FFmpeg with -cpuflags to force or disable extension families, and compare. Running the same decode/scale job with -cpuflags +avx512 versus -cpuflags -avx512 isolates the AVX-512 contribution on this exact box. If the two runs are identical, the codepath either was not present in the build or offers no gain here. Isolate the preprocessing stage. Measure decode + scale + pixel-format conversion in isolation — frames per second through the stage, not end-to-end — so the model and the GPU do not confound the number. Check that the bottleneck is here at all. If the profiler shows the GPU saturated and the CPU idle, no SIMD rebuild will help. The bottleneck is downstream. Step 5 is the one people skip. A SIMD-matched FFmpeg build is only the right lever when profiling has already established that the CPU preprocessing stage — not the model, not the GPU — owns the latency you are trying to remove. When is recompiling the right lever, versus a GPU or model change? The porting decision is a triage, not a default. Use the table below to place your situation. Decision table: which lever fits the bottleneck Profiler finding GPU utilisation Right lever Why Decode/scale loop CPU-bound, GPU idle Low (< ~50%) SIMD-matched FFmpeg rebuild The CPU stage starves the GPU; recovering CPU throughput fills the pipe without new hardware Model latency dominates, CPU stage cheap High (> ~85%) Model or GPU-level change (quantization, batching, bigger GPU) Preprocessing is not the constraint Both stages contended Mixed Rebalance first, then rebuild Fix scheduling/overlap before micro-optimising a stage AVX-512 absent on this Ryzen generation Any AVX2 tuning + threading, not AVX-512 The codepath cannot fire; chase the achievable win Decode is hardware-decodable (H.264/HEVC) Low Consider GPU/VAAPI decode offload Some decode work belongs off the CPU entirely The recompile is attractive because it is low-risk and cheap: you rebuild a well-tested open-source binary with microarchitecture-appropriate flags and measure. It does not touch the model weights, the serving runtime, or the accelerator. That is exactly why it routes cleanly into an audit sprint — it is a self-contained change with a clean before/after measurement. The build flags themselves matter here; how -march, -O2, and -O3 interact with SIMD codepath selection is the subject of our companion piece on GCC optimization flags for a port, and -march=native on the target host is usually the cleanest way to let the compiler match the silicon. Deciding whether the CPU stage is genuinely the bottleneck — rather than something you assume is — is a profiling question, and profiling methodology is where that determination is actually made. The reasoning applies equally when the constraint turns out to be memory bandwidth rather than compute, a common surprise on high-resolution frame scaling. How do you measure whether the rebuild actually helped? A SIMD porting change is only worth keeping if it moves a number that connects to cost. Measure the same metrics the serving path already reports: Frames per second per core through the preprocessing stage, before and after. This is the direct throughput signal (operational measurement, on this specific host — not a portable benchmark rate). CPU utilisation for the same frame rate. A win often shows up as the same throughput at lower CPU, which is freed headroom rather than higher peak. Preprocessing’s share of end-to-end p95 latency. If the stage was 30% of p95 before and 18% after, that is the number a cost-per-request model consumes. The reason to anchor on FPS-per-core and CPU headroom rather than a raw GFLOPS figure is that vector throughput on paper does not predict media pipeline speed — decode is branchy and memory-bound in places SIMD cannot touch. We unpack why in what GFLOPS on CPU actually measures and, more broadly, what processor throughput means for inference in practice. The honest measurement is the pipeline, not the peak. This is the same instrumentation an inference cost audit baselines. Whether CPU-side media preprocessing is the bottleneck a SIMD-targeted rebuild should address — before anyone touches the model or the GPU — is exactly what the profiler findings in our Inference Cost-Cut Pack are built to surface. If you want the broader engagement model around this kind of targeted optimisation, our services page describes how a rebuild like this routes into a scoped sprint. FAQ How does FFmpeg AVX-512 performance on AMD Ryzen actually work? FFmpeg ships hand-written SIMD implementations of its decode, scale, and filter routines and selects one at runtime based on the instruction-set flags the CPU reports. On AMD Ryzen, whether the AVX-512 codepath fires depends on the generation, and on Zen 4 the 512-bit instructions run over 256-bit units (double-pumping). In practice it means a generic build may never use AVX-512 on your box, and even where it does, the speedup is a per-target measurement rather than a guarantee. Which AMD Ryzen generations expose AVX-512, and how does its microarchitectural width affect FFmpeg codepath selection? Zen 3 and earlier expose no AVX-512, so FFmpeg falls back to AVX2 (256-bit). Zen 4 exposes AVX-512 but executes it over physically 256-bit vector units by double-pumping, while Zen 5 moves toward a wider, more native implementation. A codepath tuned for a native 512-bit unit will not deliver the same relative gain on double-pumped Zen 4 and will not fire at all on Zen 3, which is why the codepath choice must be verified against the specific silicon. How do we tell whether a generic FFmpeg build is actually using the AVX-512 codepaths available on our Ryzen target? Confirm the CPU exposes the flags (grep avx512 /proc/cpuinfo or lscpu), confirm what the binary targeted (ffmpeg -buildconf), and confirm which codepath fires at runtime by comparing -cpuflags +avx512 against -cpuflags -avx512 on the same decode/scale job. If those two runs are identical, the codepath either was not compiled in or offers no gain on this host. When is recompiling or reselecting FFmpeg’s SIMD codepath the right porting lever, versus a GPU or model-level change? It is the right lever only when profiling shows the CPU preprocessing stage owns the latency while the GPU sits underutilised. If model latency dominates or the GPU is already saturated, a rebuild changes nothing and the fix belongs at the model or accelerator level. On Ryzen generations without AVX-512, the achievable win is AVX2 tuning and threading, not AVX-512. How do we measure whether a SIMD-matched FFmpeg build improved preprocessing throughput and its share of p95 latency? Measure frames per second per core through the isolated preprocessing stage before and after, the CPU utilisation needed to hold a given frame rate, and preprocessing’s share of end-to-end p95 latency. A win shows up as higher FPS per core, freed CPU headroom, or a smaller preprocessing contribution to p95 — the last of which feeds directly into a cost-per-request figure. How does CPU-side media preprocessing sit in the serving path relative to the model and GPU, and why can it become the silent bottleneck? Preprocessing — demux, decode, scale, pixel-format conversion — runs on the CPU before any tensor reaches the GPU, and it can consume a large share of pre-model latency. When that stage is SIMD-starved or single-threaded, the GPU idles waiting for frames, so adding accelerator capacity buys nothing. It becomes silent because attention defaults to the model and the profiler reading is easy to misattribute. What the rebuild really settles The porting lever here is narrow by design: a media preprocessing stage, a specific Ryzen generation, and one question — does the codepath the binary picks match the SIMD the silicon exposes. Answer it with measurement, not assumption, because on AMD “AVX-512 on” resolves differently across Zen 3, Zen 4, and Zen 5. The failure class to name in your own pipeline is the unverified codepath — a preprocessing stage whose SIMD dispatch was inherited from a generic build and never checked against the target. Profile the stage, force the flags both ways, and let the FPS-per-core delta decide whether the rebuild earns its place before anyone reaches for a bigger GPU.