高速化版+8もっと高速化。afs_analyze_xxとafs_analyze_shrink_infoを統合
高速化版+7 (結局この時点では公開しなかった)
・VC++2012のWinXP互換ビルドに変更。特に影響はないと思うけど、VS2012 Update1で利用可能になったので、念のため。
・popcntの確認をSSE4.2のフラグの有無で確認していたのを、正しくpopcntのフラグで確認するようにした。AMD Phenom等における、「SSE4.2非対応だけどpopcntはある」ケースにも対応。
・メモリアクセスパターンを変更することで、HD映像処理向けの高速化。詳細は続きに。
・AVX2対応の準備。
Haswell実機で確認後、AVX2対応版を公開できるかも?
x264のAVX2は意外と効果が小さいようで(+5%)残念だけど…afsはどうだろう…。まあ自分で試してみてなんぼですわな。
ダウンロード>>
続きに高速化の細かい話とか。
今回は、いくつかの関数のメモリアクセスパターンを変更した。
効果としては、
・主にHD映像において高速化が見込める。
・HDエンコ時に、自動フィールドシフト(afs) + QSVEnc + その他フィルタ無し、のようなエンコ時のafsの比重が非常に大きい場合、10~30%高速化。
・afs + x264guiEx + x264(preset=slow)だとx264の比率が大きいのでそんなでもない。ただ、afsがボトルネックとなり、CPUが遊んでいる場合には効果が大きく出ると思う。
afsには、メモリ空間に対し飛び飛びにアクセスする部分がある。こういった飛び飛びのアクセスは、非常に時間が掛かってしまう。
そもそも、(キャッシュに入っていない)メモリアクセスというのはとんでもなく遅い。メモリ上を飛び飛びにアクセスしていると特にひどい。
これに対し、
オリジナルのafsでは、
・MMXの使用により、64bitまとめて処理
→64bitずつのアクセスになり、メモリアクセスの回数自体が減る。
により高速化していたし、さらに
これまでの高速化版では、
1. SSEの使用により、128bitずつ処理
2. prefetch命令の挿入により、必要になる飛び飛びのメモリの断片を明示的に先読み
して高速化していた。prefetch命令の挿入は非常に効果が大きかった(高速化の1/3ぐらいはprefetch命令のおかげだった)。
しかし、いくら先読みしているとはいっても、煩雑な飛び飛びのアクセスをしていることには変わりなく、根本的な解決にはなっていない。
今回の高速化版では、なるべく連続的なメモリアクセスをするようにプログラムを変更した。こうすることで、
・prefetch命令不要
・効率的なメモリアクセス
となり、さらに高速化できた。
HD映像で効果が強く、SD映像の場合にはそれほど効果がないように思う。
SD映像の場合は1フレームのデータが小さいので、フレーム全体がキャッシュに乗りやすい。キャッシュに乗ってさえいれば飛び飛びのメモリアクセスもどうということはないので、もともと高速に処理されていて、今回のメモリアクセスパターンの変更が大きな意味を持たないのかな、と思う。
参考:
L1キャッシュ = 32KB/core
L2キャッシュ = 256KB/core
L3キャッシュ = 8MB/CPU (Core i7 2xxx/3xxxの場合)
YC48 SD = 720x480x6 = 約2MB
YC48 HD = 1440x1080x6 = 約9MB
YC48 fullHD = 1920x1080x6 = 約12MB