Introduction to AVX2 optimizations in x264に詳しく関数ごとの高速化率とか書いてあって面白い。2割ぐらいは速くなるのかな?
以下、
Introduction to AVX2 optimizations in x264からおおまかに意味をとると、
x264は様々なデータ型を多様なSIMD命令を使って計算している。SIMDコードのうち、128bitから256bitへ素直に拡張できるのはほんの少しで、多くはもっと複雑である。64bitから128bitへの拡張した際に倍速になることがほとんどなかったように、128bitから256bitへの移行も倍速となることはほとんどないだろう。
SSE2からAVX2への移行は、MMXからSSE2への移行と似ている部分が多いけれども、いくつかの点で異なることもある。
1つは、初期のSSE2命令は遅かったりしたけど、HaswellのAVX2命令はちゃんと速いということである。
SSE2が最初に出たときは、SSE2命令が結構遅かった。初期のSSE2はMMX命令を2回(64bit×2)とSSE2を1回(128bit×1)が同速だったり、下手するとSSE2命令1回のほうが遅いなんてこともあった。この状態が解消され、MMX命令1回とSSE2命令1回がきちんと同速になるにはCore2の45nm世代までかかった。今回はそんなことはなさそうで、HaswellではAVX2命令はちゃんと速そうだ。
2つめは、AVX2命令はなんか変なことが多くて、一部のvpermdのような命令を除くと、256bitに素直に拡張したというよりは、128bit×2をやる命令、という形で拡張されている場合が多い。これによってIntelの実装は楽になるのだけど、コードを128bitから256bitに拡張するのに余計な手間がかかったりする。
3つめは、x264が256bit幅より狭いデータを扱う関数がそれなりにたくさんあって、こうしたものに対して、有効にAVX2を使うのは非常に難しかったり、不可能だったりする、ということだ。比較的複雑な関数の多くは、AVX2に移植しても予想よりあまり効果を上げられなかったりした。
多くの関数をAVX2に移植したけれども、まだ十分な最適化を行った、という段階ではないので、まだ高速化の余地はある。実際に動かしてみると、速いだろうと思っていたコードをさらに速くする方法を見つけられたりしたし、今後もそういう発見があるだろう。加えて、まだAVX2に対応できていない関数もあるので、全体としてはあと少し最適化の余地があるように思う。
加えて言えば、x264はすべてがSIMDコードというわけではなく、実行時間の半分ぐらいは普通のCのコードなため、すべてのSIMDコードが倍速になっても、x264全体としては1.33倍しか速くならない。実際にはAVX2によって倍速になることはほとんどないので、高速化率はさらに低めだろう。
で、あとは関数ごとの高速化率の一覧が書いてある。
というわけでAVX2の実装ありがとうございます。おかげで、Haswellが期待はずれに終わる、ということは無さそう。x264が対応したことで、Haswellはぐっと魅力的なものに…。うー、早く出ろ。
もうひとつ言うなら、表はHaswellにおいての「AVXまで」vs「AVX2」の比較なので、これをSandy/Ivyと比べたらもう少し高速化率に上乗せできそうな気がする。(さらに+10%ぐらい?)
あとは、256bit幅より狭いデータを扱う場合にAVX2が効果的でない、ということだけど、裏を返すと10bit版だとより高速化できるかもしれないのかな…と思う。