x264 for cell 070412 part.2: 性能評価-CELLプロセッサ
今回は、パフォーマンス計測機能の出力結果を元に、現バージョンの性能をまとめて ...
今回は、パフォーマンス計測機能の出力結果を元に、現バージョンの性能をまとめて おきます。
x264 for cell (070412) の概要
SPE 用のコードを CPU で動作させる SPE シミュレーションモード (sim) を持っています。具体的に何をしているかと言うと、
- DMA 転送 は memcpy() で代用
- mailbox (SPE への処理依頼) は 関数呼び出し で代用
- 各 SPE で同時に複数の処理が動作しないように排他制御 (pthread_mutex 使用)
- 各 SPE が個別に持つリソースの管理
- SPE 専用のコードと同等の処理を行う CPU 版のコードを用意 (x264 自体 が対応)
です。最初から SPE での動作を目指すと、実際に動作し始めるまでの難関 (メモリの制限や複雑な DMA 転送) が多いため、バグが取れずに挫折する可能性 が高いと感じ、このモードを付けています。このモードにより、実際の開発はほ とんど Linux PC 上で行っており、結果を確かめながら変更していくことが出来 ました。但し、ソースが非常に複雑 (#ifdef の嵐)になってしまっています。
上記の複雑な DMA 転送というのは、参照画像から実際に動きベクトル探索で 利用する部分を切り出す処理に相当するのですが、具体的には以下の 2 つです (当然、他にもDMA 転送しているデータはあります)。
- 192 line の DMA リスト転送 (整数画素単位の動きベクトル探索用に 256x192 の輝度部分画像 1 枚分)
- 120 line の DMA リスト転送 (1/2, 1/4 画素単位の動きベクトル探索用に 48x24 の輝度部分画像 4 枚分と 32x12 の色差部分画像 2 枚分 (24*4+12*2) )
両者ともに画像の切り出し位置は、DMA の 16byte アラインを考慮して SPE 側で計算しています (CPU 側が SPE で使用しているデータを把握していないとい うことです。デバッグ時はこれが一番問題に、、)。
また、両者ともに DMA 転送する画像の切り出し位置が処理の直前にしかわか らない、かつ、前者は DMA リスト転送するかどうかを判定する場所が複数ありま す。よって、(ようするに非常に複雑なので) ダブルバッファ等を使用することで 転送中も演算処理を行って転送時間を隠蔽するのが高速化の基本ですが、現在の バージョンでは行っていません。
各 SPE への処理の割り当ては、基本的には符号化対象画像毎に割り当ててい ますが、P (前方参照のみ) の場合と B (前方参照と後方参照) の場合で、処理量 の差が約 2 倍 ( P>B ) ありましたので、何番目の参照画像かも考慮することで 処理量を平均化しています。
テスト条件
テスト用の動画は SOCCER_704x576_60_avc_3000.yuv を使用し、以下のように動きベクトル探索を最大限行うようオプションを付けて実行しています。
$ ./x264 --bframes 3 --ref 5 --mixed-refs -A all --me umh --bime -m 7 --8x8dct \
--threads (thread num) SOCCER_704x576_60_avc_3000.yuv -o (出力ファイル名)
Cell 対応による速度の変化
まずは、x264 を Cell 対応することで、速度がどうなったか?また、実際に SPE を使用 することで速度がどうなったかです。version は以下を表し、 速度の指標は x264 自体がエンコード後に出力する fps (frames per second) を使用します。
- r635: rev:635 オリジナル版
- r635 cell sim: rev:635 の Cell 対応 (sim) 版
- r635 cell: rev:635 の Cell 対応版
| CPU/SPE | version | thread num | fps |
|---|---|---|---|
| 1PPE | r635 | 1 | 1.44 fps |
| 1PPE | r635 cell sim | 0.56 fps | |
| 1PPE/6SPE | r635 cell | 1.28 fps | |
| core2duo (E6600) | r635 cell sim | 2.70 fps |
以上のように、Cell 対応をすることで、速度が約 1/3 (1.44 -> 0.56) になっていますが、 実際に SPE を使用することで挽回 (0.56 -> 1.28) しています。現状、それでも 1PPE の ほうが速いわけですが、、参考までに core2duo (E6600) での結果も載せていま す、、完敗してます。
また、処理のほとんどを SPE に移した関数 (x264_me_search_ref()) の時間を google performance tool で測定してみましたが、実行時間に対する割合は 55% (r635) -> 40% (r635 cell) ということであまり減っていません。 これは、以下の理由が挙げられます。
- SPE に処理を依頼するためのパケットの複製 (オリジナルでは複製する必要が ない) に時間がかかっている。
- PPE 側に残した処理は、使用するデータのランダム性が高いため、キャッ シュミスが大量に発生している。
- sched_yield() 呼びすぎ (PPE が SPE に依頼する処理としては粒度が小さいすぎる)。
スレッド数増加による速度変化
次に x264 の --threads オプションで同時に処理するフレーム数 (thread num) を変化させた 場合の結果です。
| CPU/SPE | version | thread num | |||||
|---|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | ||
| 1PPE | r635 | 1.44 fps | 1.77 fps | 2.02 fps | 2.10 fps | 2.09 fps | 2.09 fps |
| 1PPE/6SPE | r635 cell | 1.28 fps | 1.55 fps | 1.94 fps | 2.04 fps | 2.06 fps | 2.06 fps |
このように thread 数が多くなると 1PPE r635 でも SMT が効いて速くなり ますが、thread 数が増えるにつれて r635 cell 版も 6 SPE が有効に働くよう になり、両者がほぼ同じ (やや負け) 位の速度でエンコード出来るようになって います。
SPE の稼働率
最後は、じゃあ SPE はどのくらい有効に働いているの?ですが、
- active rate: SPE で何らかの命令を実行している時間の割合。
- proc rate: 上記でかつ、(DMA 転送待ちに関連しない) 命令を実行してい る時間の割合。
とすると、thread オプションに対する各 SPE の active rate, proc rate は以下のようになります。
| thread num | SPE num | active rate | proc rate |
|---|---|---|---|
| 1 | 0 | 8.785670 % | 56.992781 % |
| 1 | 7.836577 % | 62.490412 % | |
| 2 | 9.204857 % | 59.048293 % | |
| 3 | 7.165960 % | 62.844794 % | |
| 4 | 8.986283 % | 59.062187 % | |
| 5 | 7.035920 % | 63.182083 % | |
| 2 | 0 | 10.107968 % | 58.416470 % |
| 1 | 10.614589 % | 57.817723 % | |
| 2 | 10.468447 % | 58.328175 % | |
| 3 | 10.941708 % | 57.527256 % | |
| 4 | 9.579995 % | 58.968929 % | |
| 5 | 11.060721 % | 57.915997 % | |
| 3 | 0 | 13.042938 % | 56.386892 % |
| 1 | 13.761920 % | 56.516727 % | |
| 2 | 13.516308 % | 57.191141 % | |
| 3 | 14.277174 % | 56.623944 % | |
| 4 | 12.060944 % | 55.693047 % | |
| 5 | 14.179765 % | 56.892087 % | |
| 4 | 0 | 13.767162 % | 57.188217 % |
| 1 | 13.889416 % | 55.032239 % | |
| 2 | 14.238510 % | 57.168836 % | |
| 3 | 14.951388 % | 56.861344 % | |
| 4 | 13.150053 % | 57.438491 % | |
| 5 | 14.789294 % | 56.637078 % | |
| 5 | 0 | 14.068798 % | 56.949056 % |
| 1 | 14.711695 % | 56.617446 % | |
| 2 | 14.316511 % | 56.909902 % | |
| 3 | 15.203619 % | 56.853118 % | |
| 4 | 13.312675 % | 57.666773 % | |
| 5 | 15.163975 % | 57.012929 % | |
| 6 | 0 | 14.075775 % | 57.279934 % |
| 1 | 14.796232 % | 56.791326 % | |
| 2 | 14.559752 % | 57.344442 % | |
| 3 | 14.659463 % | 55.245073 % | |
| 4 | 13.371265 % | 57.493847 % | |
| 5 | 15.155458 % | 57.292702 % |
--bframes や --ref オプションの値にもよりますが、各 SPE への処理の 平均化は全体的にはうまくいっているようです。
SPE が有効な演算をしている割合 (有効稼働率) は active rate * proc rate / 100 となりますが、thread 数が 6 の時の SPE 有効稼働率は、平均 active rate を 14.5 %、平均 proc rate を 57 % とすると、 14.5 * 57 / 100 = 8.25 % ということになります。


