Aviutl GPUフィルタ(OpenCL版) clfilters

GWの前半は、x264guiEx 3.00の導入方法を紹介する動画を作っていたのだけど、GWの後半の時間で、以前要望いただいた各GPUフィルタのAviutl版を作った。

ひとつのフィルタの中に、複数のGPUフィルタを含んでいて、これらを一括して使えるようになっている。

以前、同じようなNVEncのCUDA実装をAviutlに移植したCUDA フィルタを作成したことがあったのだけど、CUDAだと(当然)NVIDIA GPUでしか使用できないというのが難点。

そこで今回は、Intel / NVIDIA / AMD のいずれのGPUでも使用できるようにQSVEnc/VCEEncのOpenCL実装をAviutlに移植したOpenCLフィルタにしてみた。





対応しているフィルタはいまのところ11種類で、適用順は固定で下記の通り。

- 色空間変換
- nnedi
- ノイズ除去(knn)
- ノイズ除去(pmd)
- ノイズ除去(smooth)
- リサイズ
- unsharp
- エッジレベル調整
- warpsharp
- バンディング低減
- 色調補正

将来的には適用順を変更できるようにしたいところ。

また、現状時間方向に参照が必要なフィルタ(3Dフィルタ)には対応できていない。ちょっとどう実装したらよいかわかっていないので、当面は非対応の予定。



QSVEnc / NVEnc / VCEEnc フィルタとの違い



基本的には、QSVEnc / NVEnc / VCEEncのVppフィルタをほぼそのまま移植したものなの。ただ、QSVEnc / NVEnc / VCEEncでは速度重視なので、出力色空間に応じてなるべく軽い色フォーマットで処理している。(YUV420 8bit/16bitが多いと思う)。

一方、今回作成したAviutl版は、一貫してYUV444 16bitで処理するので、特に色差成分について少し結果が違いそう。(そう大きな差ではないはずなので確認用としては十分だとは思う)



ダウンロード>>

clfiltersの詳細



処理概要



Aviutlの内部フォーマット(YC48)からGPUで扱いやすいYUV444 16bitに変換てから、GPUに転送してフィルタ処理を行う。その後、処理結果をCPUに転送し、YC48に戻して処理を完了させている。

YC48 → YUV444 16bit → GPUに転送 → VppフィルタをGPUで連続処理 → CPUに転送 → YUV444 16bit → YC48



GPUフィルタの高速化



以前のCUDA版ではcufiltersでは行っていなかった最適化を真面目に行った。

GPUフィルタの課題

GPUで高速にフィルタ処理ができたとしても、残念ながらGPUフィルタが高速とは限らない。

- CPU-GPU間転送が遅い
Aviutlでは基本的にはフレームのデータがCPUにあるため、GPUフィルタを適用する場合、CPU-GPU間の転送が往復で必要になる。ところがこれはかなり遅い処理で、転送開始のレイテンシも大きいし、転送にも時間がかかる。

- そもそもGPUでの計算開始が遅い。
すぐに計算を行ってくれるCPUと異なり、GPUに計算を発行してから実際に開始されるまでにそれなりの遅延がある。

CPU-GPU間転送や、GPUの処理開始遅延の影響で、計算を直列に並べると、フィルタによっては普通にCPU版をAVX2とかで最適化したほうが高速ということになってしまう。GPU版を高速にするためには、

- CPU-GPU間転送を減らす
- CPU-GPU間転送やGPU計算を並行して実行する

などの対策が必要になる。



実施済みの最適化



いくつかの最適化に段階的に取り組んでみた。

初期版: CPU-GPU間転送を減らす

複数のGPUフィルタを一度に適用することで、CPU-GPU間転送を削減。GPUフィルタをひとつひとつ適用するのに比べ、転送回数を減らすのが狙い。

初期版: 内蔵GPU使用時のCPU-GPU間転送の削減

Intel GPUなど、内蔵GPUを使用する場合、OpenCLのAPIを適切に使うことでCPU-GPU間転送をなくすようにした (いわゆるZero Copy)。

最適化1: CPU-GPU間転送とGPU計算を並行して実行

保存時にはフレームを先読みすることで、CPU-GPU間転送とGPU計算を並行して行うことで、CPU-GPU間転送や処理開始の遅延を抑制した。(実装の単純化のため、保存時のみ行っており、編集時は行っていない。)

最適化2: メモリ確保・解放の削減 (NVIDIA)

もともとのOpenCL実装はIntel/AMD GPU向けで、これらのGPUでは cl_khr_image2d_from_buffer というOpenCL拡張が問題なく使えたので、これを前提にした最適化をしてしまっていた。

一方、NVIDIAはこの拡張には対応していないようで(CUDAでは似たようなことできるのに何で?)、この拡張を使わずに動作させるために、メモリ確保・コピー・解放を毎フレーム行ってしまっていた。GPUのメモリ確保・解放はかなり遅いので、メモリを使いまわすようにしてメモリ確保・解放をなるべくしないようにした。

最適化3: さらなるメモリ確保・解放の削減

意図せずメモリ確保・解放を連発していた個所が残っていたので修正。

最適化4: 不要な同期の削除

まだGPUが遊んでいる時間が多い状況だったので、VTuneなどを使って、OpenCL APIの呼ばれ方などをチェック。OpenCLリソースの解放漏れにより、無駄な同期がかかってしまっているようだったので、これを解消して高速化。



保存時の処理速度



実際にベンチマークプラグインを使って処理速度を測定してみた。

入力
sakura_op.mpg 1280x720 30fps 3501frame

環境
Win11 x64
Aviutl 1.10
Intel i9 12900K + Intel iGPU HDG770
NVIDIA GeForce RTX2070

有効フィルタ (3つ)
pmd_mt 回数:2, 強さ:100, 閾値:100
リサイズ 1280x720→1920x1080 spline36
エッジレベル調整 強さ:5, 閾値:20, 黒:0, 白:0



え~と、CPUのほうが速くね...? 悲しみ。

まあ、それはおいといて、最適化1~4によってだいぶ高速化できていて、特にRTX2070では最初の実装から比べると3.3倍速くすることができた。GPUではこうした細かな最適化の効果が大きいようで、やはりGPUフィルタではいろいろチェックすべきことが多そう。

ただ、そうは言っても、現状でも最適化されたCPUフィルタよりは遅くなってしまっている。やはりCPU-GPU間の転送や色フォーマットの変換など、GPUフィルタ特有のオーバーヘッドがいろいろ載ってくるため、今回試したような比較的軽量なフィルタではAVX2等で最適化CPUフィルタのほうが高速、ということになってしまった。

もちろん、現時点で最新のCPUのi9 12900Kと、1世代前のGPUのRTX2070での戦いなので、CPUとGPUの性能比によっては逆転することもありそうだし、もっと重いフィルタ(nnediやsmooth)を使えば、GPUのほうが有利になっていくとは思う。

また、今回はベンチマークプラグインで計測したので、デコードとフィルタだけがぶん回っている状況だけど、本来はエンコードも行うことになると思う。なので、GPUフィルタがCPUより遅いから無意味ということはなくて、CPUでの演算をGPUに移すことで、CPUがエンコードに回せる時間が増えるといったメリットもあるかもしれない。

# まあもともとはGPUフィルタの効果の確認用なので、このぐらい出ていれば十分?
スポンサーサイト



コメントの投稿

非公開コメント

No title

ありがとうございます。
これでいろいろ作業が捗ります。
プロフィール

rigaya

Author:rigaya
アニメとか見たり、エンコードしたり。
連絡先(@を半角にしてください!)
rigaya34589@live.jp
github

最新記事
最新コメント
カテゴリ
月別アーカイブ
カウンター
検索フォーム
いろいろ
公開中のAviutlプラグインとかのダウンロード

○Aviutl 出力プラグイン
x264guiEx 3.xx
- x264を使用したH264出力
- x264guiExの導入紹介動画>
- x264guiExの導入
- x264guiExのエラーと対処方法>
- x264.exeはこちら>

x265guiEx
- x265を使用したH.265/HEVC出力
- x265guiExの導入>
- x265.exeはこちら>

QSVEnc + QSVEncC
- QuickSyncVideoによるHWエンコード
- QSVEnc 導入/使用方法>
- QSVEncCオプション一覧>

NVEnc + NVEncC
- NVIDIAのNVEncによるHWエンコード
- NVEnc 導入/使用方法>
- NVEncCオプション一覧>

VCEEnc + VCEEncC
- AMDのVCE/VCNによるHWエンコード
- VCEEnc 導入/使用方法>
- VCEEncCオプション一覧>

svtAV1guiEx
- SVT-AV1によるAV1出力
- svtAV1guiExの導入>
- SVT-AV1単体はこちら>

ffmpegOut
- ffmpegを使用した出力
- ffmpegOutの導入>


○Aviutl フィルタプラグイン
自動フィールドシフト (ミラー)
- SSE2~AVX512による高速化版
- オリジナル: aji様

clfilters 
- OpenCLベースの複数のGPUフィルタ集
- 対応フィルタの一覧等はこちら

エッジレベル調整MT (ミラー)
- エッジレベル調整の並列化/高速化
- SSE2~AVX512対応
- オリジナル: まじぽか太郎様

バンディング低減MT (ミラー)
- SSE2~AVX512による高速化版
- オリジナル: まじぽか太郎様

PMD_MT
- SSE2~AVX512による高速化版
- オリジナル: スレ48≫989氏

透過性ロゴ (ミラー)
- SSE2~FMA3によるSIMD版
- オリジナル: MakKi氏

AviutlColor (ミラー)
- BT.2020nc向け色変換プラグイン
- BT.709/BT.601向けも同梱

○その他
x264afs (ミラー)
- x264のafs対応版

aui_indexer (ミラー使い方>)
- lsmashinput.aui/m2v.auiの
 インデックス事前・一括生成

auc_export (ミラー使い方>)
- Aviutl Controlの
 エクスポートプラグイン版
 エクスポートをコマンドから

aup_reseter (ミラー)
- aupプロジェクトファイルの
 終了フラグを一括リセット

CheckBitrate (ミラー, 使い方, ソース)
- ビットレート分布の分析(HEVC対応)

チャプター変換 (使い方>)
- nero/appleチャプター形式変換

エッジレベル調整 (avisynth)
- Avisynth用エッジレベル調整

メモリ・キャッシュ速度測定
- スレッド数を変えて測定

○ビルドしたものとか
L-SMASH (ミラー)
x264 (ミラー)
x265 (ミラー)
SVT-AV1 (ミラー)

○その他
サンプル動画
その他

○読みもの (ミラー)
Aviutl/x264guiExの色変換
動画関連ダウンロードリンク集
簡易インストーラの概要

○更新停止・公開終了
改造版x264gui
x264guiEx 0.xx
RSSリンクの表示
リンク
QRコード
QR