10月
24
Ut Video Codec Suite はマルチスレッドエンコード/デコードをサポートしています。ULxx においてはスレッドへの分割は映像を横長の帯(これを band といいます)に分割して割り当てるのですが、分割後の処理中にスレッドが CPU コアをまたぐとキャッシュミスして遅くなるので、以下の対策を実装してあります。
- 各スレッドは SetThreadAffinityMask API を使って、単一の論理プロセッサに束縛させる。
- スレッドごとに job queue を持ち、各 band は上から順番に特定のスレッドの job queue に放り込む。これは、エンコード時に一旦マルチスレッド処理した後シングルスレッド処理し、再びマルチスレッド処理する際に、band が前半と後半で異なるスレッド(= 異なる論理プロセッサ)で処理されて各コアのキャッシュ間で途中経過のデータを転送して遅くなるのを避けるため。
さて、Win32 ではこれでいいのですが、POSIX 環境のスレッドである pthread には、移植性のある SetThreadAffinityMask 相当の API がありません。そこで、上記の対策を全くとらなかった場合にどれくらい遅くなるかを計測しました。
で、結果なんですが…
- SetThreadAffinityMask を呼ばない場合(スレッドが自由に論理プロセッサ間を動くことができる)、呼んでかつ走るスレッドが HT で物理コアを共有しない場合とおおむね同様のパフォーマンスになるが、時々かなり遅くなる(HT で物理コアを共有したときと同様のパフォーマンスになる)。同じように計測しても速かったり遅かったりするので、どういう条件で遅くなるのかはサッパリ分からない。
- SetThreadAffinityMask の代わりに SetThreadIdealProcessor を呼んだ場合、やはりおおむね同様のパフォーマンスになり、しかも上の「時々遅くなる」という症状は発生しない。さらに、SetThreadAffinityMask で単一の論理プロセッサに束縛するのではなく「ルーズな」指定のため、スレッドが物理コアを共有する事態を OS が勝手に回避してくれる。
- job queue をスレッドごとに作らずに全体で 1 つにしても、SetThreadAffinityMask 云々にかかわらずパフォーマンスは変わらない。
表になって無くて申し訳ない。
SetThreadAffinityMask も SetThreadIdealProcessor も呼ばない場合に時々遅くなるのが非常に気持ち悪いのですが、とりあえず Ut Video Codec Suite の次のバージョンでは SetThreadIdealProcessor に置き換えるようにしようと思います。ただこの辺の指定って論理プロセッサが 64 個を超えると、必ずしも意図したとおりにはならないんですよね。
job queue に関しては副作用無く削除できるようなので、安心して削除できます。実装するときに結構苦労した気がしますが(^^;
マルチスレッド関連の話でutに限らずLagarithもなんですがAMDのLlanoことA8-3850(4core)だとCPU使用率が40%前後で上がらないんですよね・・・
aviutl(システムの画像スレッド数個別指定)・VirtualDub-AMD・vctestでの話です。
x264単体・x264guiEx経由だと100%近くまで使ってくれます
OSをXPにしたら解決したという書き込みも見たのでwin7x64が問題なのかもしれませんと一応報告させて頂きました
と連投ですみません
fancycache入れてたせいで使用率が上がらないようでした
外すと使用率は75-77まで上がりました。
どっちにしろ使用率は80あたりで頭打ちっぽいです・・・
実際にコーデックが使用される時は、他の(シングルスレッドの)処理が入ったり、あるいは HDD アクセスを待たされたりして、あまり CPU 使用率は上がらないものです。80% 使えていれば良好だと思いますよ。
お返事ありがとうございます
HDD別にしたりサービスをgameboosterとかで減らしてても
vctestでAMVでエンコ4スレッド指定で30弱ut60パーと安定しません
CPUのクロックは固定してるんですけどね
しばらく暇な時にでも試行錯誤してみます
ありがとうございました
あ、あとvctestはコーデックの処理時間を正確に測るために(シングルスレッドで)他の処理をたくさんしているので、タスクマネージャで見えるCPU使用率はかなり低くなります。そういうものとしてお使いください。