« アルファブレンドを Core 2 Duo で計る | メイン | トラックバック spam 対策を少しずつ »

2007年12月01日

動画再生エンジン開発日誌:: 動き補償の SSE2、SSE3 化

    

libtheora の MMX をアセンブリからイントリンシックを使ったCに書き換えたので、ちょっと SSE2、SSE3 対応でもしてみようかなと動き補償部分の SSE2、SSE3 化を行うことにした ( SSE3 は _mm_lddqu_si128 しか使ってない ) 。
で、書き換えて計測してみると…… 遅い。
MMX 版より遅くなってる。
なぜ? と思ってプロファイルを取ってみる。
すると、SSE2、SSE3 化した関数は速くなってる。
なのに、全体では遅い。
プロファイルの結果の見方が違うのかなぁ…… なんだろうと悩みつつ、SSE3 を使わないようにしてみるともっと遅くなった。
_mm_lddqu_si128 の効果はあるようだ。
動き補償では、過去の画像の任意のブロックをコピーしてくるので、アライメントはあっていない。
SSE2 では、_mm_loadu_si128 で読み込む必要がある。SSE3 はより速い _mm_lddqu_si128 が使える。

そこで SSE2 で本当に速くなるのか見るために アルファブレンドを Core 2 Duo で計ってみた
結果速くなった。

なんだろう? と考えていて気付く。
メモリが遅いんだ。
確かプリフェッチがあったはずと探すと SSE に _mm_prefetch があった。
1 キャッシュ・ライン分は、32 バイトか 64 バイトらしい。
と言うこで、32 バイトとして _mm_prefetch することにした。
処理の直前でプリフェッチしても意味がないはず。
IDCT などは計算だけでメモリアクセスはない。
そこで、IDCT の次にある動き補償でアクセスするブロックを IDCT の前にプリフェッチするようにした。
速くなった。
他にもプリフェッチする場所を増やしていくと、速くなっていく。
なんてお手軽なんだ……
まあ、逆に遅くなる場合もあるので、計測しながら適切な場所に入れていく必要はあるけど。

MPEG と theora では、SIMD 化できそうな処理は、共通化できるものが多い。
とは言っても、theora で SIMD 化されているのは、IDCT と動き補償、デブロッキングフィルタ のみなのだが。

で、このうち IDCT と動き補償は共通化出来そう。
どちらかの改良が他でも活きるのはいい感じだ。
ただ、動き補償は少し違う。
theora では、単純コピー、IDCT の結果に+128したもの、IDCT の結果と合成、IDCT の結果と2ブロックの合成の4種類で、合成は切り捨て。単純コピーは、まとめて行われていて処理は分離されていない。
MPEG は、単純コピー、2ブロック合成、4ブロック合成、DCT の結果そのまま、IDCT の結果と合成、IDCT の結果と2ブロックの合成、IDCT の結果と4ブロックの合成の7種類で、合成は四捨五入。
IDCT の結果と合成は四捨五入はない。
と言ううことで、共通するのは IDCT の結果と合成のみになる。
ただ、どれも似たような処理なのである程度使いまわせる。
問題は、MMX版、MMX2版、SSE版(プリフェッチを使う)、SSE2版、SSE3版(_mm_lddqu_si128を使う)と、やたら関数が増えることだな。
10種類の関数 * 5 で 50個か…… まあ、関数によっては使わないのもあるので、だいぶ減るとは思うが多いな。
IDCT はたぶん共通化できるはず。theora のソースを見た感じでは LLM ではないようだけれど。



投稿者 Takenori : 2007年12月01日 02:37




comments powered by Disqus
Total : Today : Yesterday : なかのひと