テーブル処理による速度改善

処理速度改善としてテーブル処理を復活しました(全部は復活していませんが)。これは元々lameが持っている高速化処理ですが、LSの空きを稼ぐために前回は使用していませんでした。今回はPCMデータと生成したMP3データをMFCで転送しながら処理することで、フルサイズのバッファを持たないようにしてLSの空きを稼いでいます。いちおうダブルバッファによる転送でいわゆるレイテンシー削減も実現していると思います。

パッチはこちらです。

5月16日追加
上記パッチはlog_tableの初期化処理を実行していない不具合があります。実行速度にも影響します(遅くなります)ので、以下の結果は信頼できる数値ではありません。注意してください。

修正のポイント

PCMを保持する領域と生成したMP3データを保持する領域がかなり大きかったので、ダブルバッファで転送しながら処理するように変更しました。これによりLSの使用量は減るしレイテンシーも減ります。ただ今回の場合レイテンシーの問題は全体から見るとびびたるものです。他にもメインメモリから必要なときに転送してきて処理するようにしてLSの使用量を削減しています。

これらの変更の結果、lameの持つ主なテーブル処理を復活しています。pow43テーブルは大きさのわりにあまり使ってなさそうなので、テーブル処理になっていません。

SPUは相変わらず一基しか使いませんし、PPUとSPUの並列処理もしていません。

結果

今回の結果は以下の通りです。もちろん前回と同じwavファイルを使用しています。

376993507357: (246620604): LAME version 3.96.1 (http://lame.sourceforge.net/)
376993532028: (246645220): Using polyphase lowpass filter, transition band: 17249 Hz - 17782 Hz
376993541245: (246654413): Encoding starwars.wav to starwars.wav.mp3
376993548630: (246661778): Encoding as 44.1 kHz 128 kbps j-stereo MPEG-1 Layer III (11x) qval=3
376993677593: (246790387):     Frame          |  CPU time/estim | REAL time/estim | play/CPU |    ETA
376993682024: (246794807):      0/       ( 0%)|    0:00/     :  |    0:00/     :  |         x|     :
376994041887: (247154575):      0/117    ( 0%)|    0:00/    0:00|    0:00/    0:00|   0.0000x|    0:00
377346413049: (599981776):     50/117    (43%)|    0:00/    0:00|    0:00/    0:00|   130.61x|    0:00
377764491603: (1018405980):    100/117    (85%)|    0:00/    0:00|    0:00/    0:00|   261.22x|    0:00
377898663193: (1152690216):    114/117    (97%)|    0:00/    0:00|    0:00/    0:00|   297.80x|    0:00
377898758535: (1152785300): Writing LAME Tag...done
377898764143: (1152790890): ReplayGain: -7.5dB
(157073253726-156167967751)/3000000000=0.302 [sec]

PPUの速度まで達していませんが、約10倍速となり、前回からかなり改善しました。lameの元々の高速化処理をなめてはいかんですな。

パフォーマンス解析結果は以下の通りです。今回は上記と同じ3秒のwavファイルで試しました。Athlon64は速くていいです。

systemsim % mysim spu 6 display statistics
SPU DD3.0
***
Total Cycle count               1491419225
Total Instruction count         643
Total CPI                       2319469.88
***
Performance Cycle count         1491419225
Performance Instruction count   864859095 (807032455)
Performance CPI                 1.72 (1.85)

Branch instructions             39562467
Branch taken                    32060387
Branch not taken                7502080

Hint instructions               9964429
Hint hit                        24711617

Contention at LS between Load/Store and Prefetch 24902328

Single cycle                                         550683203 ( 36.9%)
Dual cycle                                           128174626 (  8.6%)
Nop cycle                                             17392180 (  1.2%)
Stall due to branch miss                             154456872 ( 10.4%)
Stall due to prefetch miss                                1422 (  0.0%)
Stall due to dependency                              575093941 ( 38.6%)
Stall due to fp resource conflict                            0 (  0.0%)
Stall due to waiting for hint target                  22498559 (  1.5%)
Stall due to dp pipeline                                     6 (  0.0%)
Channel stall cycle                                   43118407 (  2.9%)
SPU Initialization cycle                                     9 (  0.0%)
-----------------------------------------------------------------------
Total cycle                                         1491419225 (100.0%)

Stall cycles due to dependency on each pipelines
 FX2        62338407 ( 10.8% of all dependency stalls)
 SHUF       126397818 ( 22.0% of all dependency stalls)
 FX3        13718179 (  2.4% of all dependency stalls)
 LS         170538397 ( 29.7% of all dependency stalls)
 BR         158320 (  0.0% of all dependency stalls)
 SPR        1320 (  0.0% of all dependency stalls)
 LNOP       0 (  0.0% of all dependency stalls)
 NOP        0 (  0.0% of all dependency stalls)
 FXB        0 (  0.0% of all dependency stalls)
 FP6        146239895 ( 25.4% of all dependency stalls)
 FP7        55701599 (  9.7% of all dependency stalls)
 FPD        6 (  0.0% of all dependency stalls)

The number of used registers are 128, the used ratio is 100.00
dumped pipeline stats
systemsim %

こちらでは1491419225サイクル(約0.5秒なので6倍速相当)で、上記結果より悪いです。どちらを信じるかといえば、こちらの方が実機に近いのでしょう。

CPIは前回より少し改善し2命令同時実行の割合も増えましたが、CPUは1.72ですし、2命令同時実行も全体の8%程度です。相変わらず半分以上stallしてます。良く言えば、まだまだ高速化の余地があるとも言えます。ちなみに-funroll-loopsオプションを付けると大きくなりすぎてリンクできません。

個々の数値を比較するため、前回と同じ0.5秒のwavファイルによるパフォーマンス解析も貼ります。

systemsim % mysim spu 7 display statistics
SPU DD3.0
***
Total Cycle count               223957771
Total Instruction count         643
Total CPI                       348301.34
***
Performance Cycle count         223957771
Performance Instruction count   126329269 (117534141)
Performance CPI                 1.77 (1.91)

Branch instructions             5943491
Branch taken                    4706876
Branch not taken                1236615

Hint instructions               1537589
Hint hit                        3513938

Contention at LS between Load/Store and Prefetch 3658139

Single cycle                                          78213275 ( 34.9%)
Dual cycle                                            19660433 (  8.8%)
Nop cycle                                              2790498 (  1.2%)
Stall due to branch miss                              25270000 ( 11.3%)
Stall due to prefetch miss                                 282 (  0.0%)
Stall due to dependency                               86015584 ( 38.4%)
Stall due to fp resource conflict                            0 (  0.0%)
Stall due to waiting for hint target                   3208465 (  1.4%)
Stall due to dp pipeline                                     6 (  0.0%)
Channel stall cycle                                    8799219 (  3.9%)
SPU Initialization cycle                                     9 (  0.0%)
-----------------------------------------------------------------------
Total cycle                                          223957771 (100.0%)

Stall cycles due to dependency on each pipelines
 FX2        8040486 (  9.3% of all dependency stalls)
 SHUF       19898499 ( 23.1% of all dependency stalls)
 FX3        2212448 (  2.6% of all dependency stalls)
 LS         25301434 ( 29.4% of all dependency stalls)
 BR         44546 (  0.1% of all dependency stalls)
 SPR        275 (  0.0% of all dependency stalls)
 LNOP       0 (  0.0% of all dependency stalls)
 NOP        0 (  0.0% of all dependency stalls)
 FXB        0 (  0.0% of all dependency stalls)
 FP6        23202814 ( 27.0% of all dependency stalls)
 FP7        7315076 (  8.5% of all dependency stalls)
 FPD        6 (  0.0% of all dependency stalls)

The number of used registers are 128, the used ratio is 100.00
dumped pipeline stats
systemsim %

考察

前回は全体の約40%は依存関係が原因のストールで、そのうちの約60%は浮動小数点の依存関係だったのですが、今回はそこまで多くないです。テーブル処理のおかげで浮動小数点演算自体が減ったからでしょうか。

今回気になるのはStall due to branch missです。__builtin_expect関数を使うと分岐予測を指示できるとのことなので試してみます。その後はボトルネックを調べてループアンローリングSIMD化をですかね。

><