6 ポイント 投稿者 GN⁺ 2025-07-21 | 3件のコメント | WhatsAppで共有
  • FFmpeg開発陣手書きのアセンブリコードによって最大100倍の性能向上を発表
  • 今回のパッチはプログラム全体ではなく、特定の関数でのみ高速化の効果が発生
  • 最新CPUのAVX512対応では100倍、AVX2対応では64%の性能向上を確認
  • この高速化機能は主にあまり知られていないフィルタに適用
  • コンパイラの自動最適化では、依然として手書きのアセンブリコードとの性能差が明らかに

FFmpegの性能向上:100倍高速化の実際の意味

最新パッチと主な改善点

  • FFmpegプロジェクトの開発陣が手作業で書いたアセンブリコードを適用した結果、オープンソースのクロスプラットフォームなメディアトランスコーディングツールで「100倍の高速化」という成果を強調
  • ただしこの主張について開発陣は、FFmpeg全体ではなく単一の関数にのみこの高速化が適用されることを明確に説明
  • rangedetect8_avx512関数でこの際立った最適化が行われ、最新のAVX512対応プロセッサでは最大100倍、AVX2経路では約64%の性能向上を実現
  • この機能はあまり知られていないフィルタに適用されたもので、従来は開発の優先順位が高くなかったが、今回SIMD(単一命令・複数データ)方式による並列処理の最適化を達成

開発陣の説明と技術的背景

  • FFmpeg開発陣はTwitterで「この1つの関数が100倍速くなったのであり、FFmpeg全体ではない」と明確に周知
  • 追加説明では、この機能がシステムによっては最大100%の速度向上の可能性があると明らかにした
  • こうした性能改善はSIMD技術を基盤とし、最新チップでの並列処理効率を大幅に高めた結果

アセンブリ言語を直接書く重要性

過去と現在の最適化アプローチ

  • 1980〜1990年代には、限られたハードウェア環境で手書きのアセンブリコードがゲームや各種ソフトウェアの高速化における中核的な手法だった
  • 現在では大半の最新コンパイラが高級言語のコードをアセンブリコードへ変換するが、コンパイラのレジスタ割り当てなどの最適化の限界により、手書きのアセンブリコードが依然としてより高い性能を示す
  • FFmpegはこのような最適化哲学を貫く数少ないプロジェクトの1つであり、独自のアセンブリ講座も運営している

FFmpegのエコシステムへの影響力

  • FFmpegのライブラリおよびツールはLinux、Mac OS X、Microsoft Windows、BSD、Solarisなど多様な環境で動作
  • VLCなどの人気ビデオプレーヤーでも、FFmpegのlibavcodec、libavformatライブラリを活用
  • このように幅広いオープンソースのメディアエンコード/デコードのエコシステムにおいて、FFmpegが占める技術的重要性は大きい

まとめ

  • 今回の性能向上は中核機能全体ではなく一部の関数に限られるものの、性能限界の突破を示す事例
  • 最新ハードウェア向けの特化最適化とオープンソース精神が組み合わさり、メディア処理分野で引き続き技術的な模範を示している

3件のコメント

 
bobcat 2025-07-24

これは昔も今も有効ですね
同じようにコーデックライブラリをARMへ移植しながら、SSEで書かれたカーネルを一つひとつほどくところから進めたことがあり、すべてほどいてスカラだけが残った状態で実環境のベンチマークを回したとき、性能差は有意に出ました

 
aer0700 2025-07-23

GCCよりもさらに最適化されたコードを書けるエンジニアとは……本当にすごいですね。

 
GN⁺ 2025-07-21
Hacker Newsの意見
  • 私は10年間ほどHEVCなどのSIMD最適化をしてきたが、assembly版と通常のC版を比較するのはほとんど冗談のようなものだった。100倍差のようなとてつもない数字が出るからだ。実際、こうした結果は初期実装の効率が極端に低かったことを意味する。実運用では、マイクロベンチマークのようにキャッシュが十分に温まった状態で同じ関数を何百万回も繰り返し呼ぶ環境ではない。その代わり、実際の状況では他の多くの処理の中で一度だけ呼ばれることもある。キャッシュ効果を減らすには非常に大きなテスト用メモリ領域を用意して試験すべきだが、実際にそうしているのかは疑問だ。

    • FFmpegのような動画変換ソフトウェアでも、別途「マクロベンチマーク」を行っているのか気になる。長時間にわたって性能や品質、CPU使用量などをさまざまな動画と変換の組み合わせで測定していそうだが、そのためには専用の一貫したハードウェアが必要だと思う。

    • 少し方向の違う質問になるが、SIMDの経験が豊富そうなので聞きたい。ISPCを使ったことはあるだろうか、またどう思うだろうか。今でもなおSIMDコードを手書きしなければならず、一般的なコンパイラの自動ベクトル化が弱いというのは少し信じがたい。GPUカーネルでは昔から常に自動ベクトル化されていたのとは対照的だ。

    • ffmpeg自体もマイクロベンチマークと大差ないと思う。本質的には while (read(buf)) write(transform(buf)) のような構造だ。

    • 残念ながら、キャッシュの問題以外にも、開発者が100%高速化と言っていても、実際には非常に限定的なフィルタだけに当てはまることが多かった。それでも情報はかなり透明に伝えている方だ。

    • 「初期実装が非効率だった」という解釈については、どんな数値が出るのか、結果そのものが重要だと私は思う。

  • 記事ではある箇所で100倍、別の箇所で100%高速化と書かれていて混乱する。たとえば「rangedetect8_avx512 の性能が100.73%向上」と書かれている一方で、スクリーンショットは100.73倍を示している。100倍なら9900%向上で、100%高速化なら2倍速いという意味だ。実際にはどちらが正しいのだろうか。

    • スクリーンショットにある通り、明らかに100倍(あるいは100.73倍)が正しい。それは9973%の高速化を意味する。記事本文では % 表記を誤って使ったようだ。

    • 単一関数ベースでは100倍、フィルタ全体ベースでは100%(2倍)だ。

    • ffmpeg側の主張は100倍だ。100%は記事の誤字だと思う。

    • 関数名が 8 と関係していて、8ビット値を扱う演算だとすれば、以前の実装がスカラーだった場合、AVX512では128要素を一度に処理できるので、100倍高速化もあり得ると思う。

  • ffmpeg公式のassembly記述に関するガイドもあるので、参考資料として残しておく。 https://news.ycombinator.com/item?id=43140614

  • 記事の rangedetect8_avx512 が実際にどんな場面で使われ、変換全体の中で実時間性能がどの程度向上するのかが不明瞭に感じる。これが本当に目に見える実質的な意味を持つのか気になる。

    • 昔、映像信号がアナログだった時代には、制御信号を帯域内に符号化して処理していた。DVD以降もデジタル信号がアナログ出力されていたため、色値16未満(0〜255のうち)を「黒よりも黒い」信号として使っていたし、BluRayやHDMIも同様だった。最近では0〜255の全域を使おうという流れに移っている。しかし今でも信号レンジの区別が正しく行われず、映像が暗く壊れてしまうことが多い。この関数はピクセル値が16〜255なのか、0〜255なのかを判定する用途に見える。もし16〜255であることが確実なら、エンコード時に情報を節約できる。ただしこれは推測だ。私も仕事で映像を扱うが、ブラックレベル処理をいつも上手くできないのが恥ずかしい。

    • 変換処理の中でこのフィルタが使われるのではなく、色域やアルファがpremultipliedかどうかといったメタデータ用情報を判定するために使われる。問題の関数はその中でも色レンジの判定に当たる。

  • 興味深い経験について触れたい。私が唯一assemblyコードを書いた理由もSIMDのためだった。最近その話をしたのだが、当時assemblyを書かなければならなかった理由を忘れていた。実際にはコンパイラがaliasingの問題のために、私の望む形に最適化できなかったのだ。データが別の方法でアクセスされることはないと明示し、非標準キーワードを使ったところ、コンパイラが自動的にSIMD命令を活用した。結局、自分で書いたassemblyは削除した。

  • 今回の最適化がx86/x86-64(AVX2, AVX512)にしか適用されない点は少し皮肉だ。長い間みながx86を使っていたので、SIMD最適化が広く適用される可能性があったが、新しい拡張アーキテクチャは本当に今ひとつだったり互換性が不足していたりした。そしてようやく改善されたx86 SIMDが出てきても、今やx86はもはや標準ではなく、依存しにくくなっている。

    • AVX512には複数の拡張セットがあり、基本命令だけを使わない限り、CPUごとにサポート範囲が異なることがある。最近のエンコーダはマルチスレッド性能が向上したが、限界も存在する。以前、組み込みプロジェクトでSoC側のビデオエンコーダ互換性問題に苦労した末にffmpegを動かしてみたところ、複数のCPUコアを使ってよりよい結果を得た経験がある。
  • 正直、assemblyが最適化されたCより速いというのは意外だった。今どきのコンパイラは非常に優秀だから、手書きのassemblyを使っても性能差はごくわずかだろうと思っていたが、明らかに自分の思い違いだったと気づいた。いつかはassemblyもきちんと学ばなければと思った。

    • 関連パッチを見ると、既存のbaseline(ff_detect_range_c)は非常に一般的なスカラーCコードで、高速化は同じ演算を行うAVX-512版(ff_detect_rangeb_avx512)から来ている。FFmpeg開発者はベクトル幅に依存しないマクロでassemblyを直接書くのを好むが、Intelのintrinsicsでもほぼ同じように表現できそうだ(どうせ違いはレジスタ割り当て程度で、実質的な差は大きくない)。どれだけうまくベクトル化できるかが速度差の本質だ。現代のコンパイラでは、自明でないループのベクトル化はほとんど不可能で、しかもその試行ですら gcc -O3 などのオプションが必要だ。だからこのような8ビットのように処理単位が小さい演算では、AVX/AVX2/AVX-512で手動ベクトル化すると少なくとも数十倍の性能差が出る。現代のCPUでは、極限まで最適化したスカラーコードをコンパイラ生成コードより速く書ける場合もあるが、それは非常に稀で相当気を遣う必要がある(依存チェーンやexecution portの負荷など)。実際、私自身40%の高速化を経験したことがある。関連リンク: baseline C, AVX512版

    • より低レベルの最適化に近づくと、Cコンパイラが突然奇妙な動作をする例に1時間も経たずに遭遇することになる。実際に極めて頻繁に呼ばれるコードなら、最適化の問題は本当に重要になる。例: https://stackoverflow.com/questions/71343461/how-does-gcc-not-clang-make-this-optimization-deciding-that-a-store-to-one-str

    • SIMD intrinsicsまで降りるだけでも、コンパイラ任せよりずっと簡単に性能を引き上げられる。私は実際に複数パートに分けたガイドを書いたことがある。 https://scallywag.software/vim/blog/simd-perlin-noise-i

    • ほとんどすべてのC/C++ライブラリの性能クリティカルな部分では手書きassemblyが使われている(strlen のような単純な関数も同じだ)。コンパイラはたいてい十分に良い結果を出すが、ここまで投資する価値があるほど重要なソフトウェアは少数だ。

    • 実際の性能向上はassemblyのおかげではなくAVX512のおかげだ。このカーネルは非常に単純なので、AVX512 intrinsicsで書けばCコードとassemblyの差はほとんどない。100倍の速度差の理由は、a) min/maxがSIMDでは単一命令で処理される一方、スカラーではcmp+cmovに分かれること、b) 8ビット精度なので各AVX512命令が64個を同時に処理すること、にある。結果としてL1、L2キャッシュ帯域幅まで飽和させられる(Zen 5では128B、64B/cycle)。ただしフレーム全体を処理するなら、メモリサイズの都合でL3にアクセスせざるを得ない場合があり、そのときは利得が半減し、L3にも収まらない場合は利得はさらに小さくなる。

  • Sound Open Firmware(SOF)を思い出した。これもgccと商用Cadence XCCコンパイラ(Xtensa HiFi SIMD intrinsics対応)のどちらかを選んでビルドできる。 https://thesofproject.github.io/latest/introduction/index.html#toolchain-faq

  • 100xであって、100% x ではない。