Amatsukaze 改造版 0.9.7.0

AmatsukazeのKFMフィルターを中心にGPUフィルタをRTX30xx以降向けに高速化してみた。

CUDA 11.8を使用してコンパイルしたので、CUDAの使用にあたっては、

- ドライバ 450.80.02以降
- CC 3.5(後期Kepler、GK110/GK208)以降のGPU (これは従来から変わらず)

が必要になります。




KFMによるインタレ解除は、AvisynthCUDAFiltersで実装されているのだけど、CUDAを使って計算量の多い処理をGPUである程度の速さでに実行できるようになっている。

ただ、RTX4080とかを使っても爆速とはならず、RTX2070から乗り換えた時に思ったよりは速くならないなあという印象だった。

そこで、KFMをもっと高速化できないかなあということで、これまでに新しめのCUDAでビルドできるようにして、動かない個所を修正したりしてきた。

ただ、KFMは本当にたくさんのフィルタの集合体で、GPUフィルタなのもあってこれをすべてちゃんと理解するのは難しい、というかほぼ無理…という感じ。(そもそもインタレ解除のアルゴリズム自体には全然詳しくないし)

それでも別に全体を理解しないと高速化はできないというわけではなくて、純粋にプログラミング的に高速化することは可能だと思ったので、いろいろ調べてみた。



まず、NVIDIAのプロファイラである、Nsight Systemsを使って、KFM動作中のGPUの関数のうち、どれがどのくらい時間かかっているのか、様子を確認してみる。

avisynthcudafilters_20240413_compute_cuda.png

こうしてみると、kl_searchというCUDAのkernel(関数)が計算時間の大半を占めていることがわかる。なので、普通にいえばまずはここを高速化するのが効果的なのでまずは目指すべき、ということになる。ただ、kl_searchはおそらく動きベクトル探索を行う関数で、正直中身はさっぱりわからんので、高速化といってもどうしたらいいやら…。

ということでもっと簡単に理解できて確実に効果がでそうなあたりを探してみることにした。



1. ビルドしなおす



単純に新しいCUDAの最適化に期待して、コンパイルしなおして高速化できないか、というもの。

RTX4080では高速化したが、GTX1080では逆に遅くなった。謎である。



2. 新命令(__reduce_add_sync)の活用



kl_searchの一部を確認すると、総和演算(いわゆるreduce add)を行っているところがある。

総和をとるというのはよく行う計算のわりに、GPUで高速に行おうとするとちょっと厄介な計算になる。"reduction 最適化"とかで検索すると、すぐにGPUコードの闇を感じることができる黒魔術のようなコードがいっぱい出てくるぐらいには厄介である。まあだいたいはsharedメモリを使ってどうのこうのとか、shuffle命令を使ってどうのこうのとかいうのに落ち着く。

ところが、Ampere以降のGPUには、この厄介なreductionを32個分(1 warp内)をすっきり一命令で高速に実行してくれる命令が追加されている(__reduce_add_sync)ので、これを使ってみた。KFMではkl_searchのほかにも多くの個所でこのreductionが使用されているため、多少効果があった。



3. GPU使用効率の向上



次に、プロファイル結果を見ていくと、kl_searchが重い、という以外にもわかる問題点として、kl_search以外は非常に短時間で終わるCUDAの関数(kernel)が大量に実行されている、という点である。

avisynthcudafilters_20240413_many_small_kernels.png

短時間でおわるなら問題なさそうなものだけど、実際にはこれが大量にあるとわりと問題になる。

例えば、下のような同じ関数が9回連続で呼ばれているところを見てみる。

横方向が時間経過を表していて、青い部分が関数が実際に実行されている時間になっている。

これを見ると、実はkernelの実行とkernelの実行の間に結構な隙間があって、kernelを起動するための時間が、実際の計算時間と同じぐらい(だいたい1.5usぐらい)だけ、それぞれ挟まってしまっている。

avisynthcudafilters_20240413_many_small_kernels_zoom_with_number.png

また、各kernelの計算量の目安であるスレッド数と実行時間を見比べると、計算量がある程度以上減っても、実行時間が減らないことがわかる。

番号スレッド数
(≒計算量)
実行時間
(us)
起動時間
(us)
14121604.1921.485
21105921.6961.579
3870401.4721.431
4122881.2802.106
540961.5681.650
630721.4071.550
710241.1521.250
810241.3761.500
910241.3441.250


このとこからわかるようにGPUの特性として、
- kernel切り替えに一定の時間を必要とする
- 少量の計算でも一定の時間を必要とする
というのがあるので、あまり計算量の少ない関数を大量に実行してしまうと、GPUを効率よく稼働させられないことがわかる。

今回は、これに対する古典的な高速化手法である
- 複数のkernelをひとつにまとめる
- まとめられない場合はstreamとよばれるタスクキューを複数作成し、並列に実行する
の2つを実行した。

このあたりの高速化はひとつひとつはたいして速度向上に繋がらないけれど、たくさんのものに対して行うことで、確実に効果を出していくことができるものになっている。



3-1. 複数のkernelをひとつにまとめる



計算量の少ない連続するkernelをひとつのkernelにまとめたり、計算対象ごとに複数回呼び出している関数を一括して実行するようにしたりして、とにかくkernelをまとめていく。

これによって、
- kernel呼び出し回数の削減
- 計算量増大による効率化
によって高速化できる。

たとえば、もともと

avisynthcudafilters_20240413_fuse_kernels_org.png

だったのが、kernelをまとめたあとは

avisynthcudafilters_20240413_fuse_kernels_new.png

のようになって、同じ処理を表す緑の範囲が205usから121usに短縮できたし、範囲内のkernel(青いブロック)の数もかなり減らせていることが確認できる。

まあ、まとめた後もまだまだ短時間で終了する関数ばかりだけど、これでも多少は効率化できた。正直、このぐらいではあまり効果がないのだけど、実際には、この箇所だけではなくて、こんな感じのkernelの統合を10か所以上で行って、少しずつ効果積み上げていった。



3-2. streamを使った高速化



GPUではkernelの切り替えに一定の時間がかかるというのは前に書いた通りだけど、kernelを複数並列に実行しておけば、あるkernelの切り替え中に他のkernelが実行できて高速、というのがこのstreamを使った高速化。

基本的に画像にはY,U,Vの3成分があって、フィルタ処理はこの3成分に対して並列に実行できるものが多いので、CUDAのタスクキューであるstreamを3つ使って3並列で実行できるようにしてみた。

たとえば、もともと

avisynthcudafilters_20240413_stream_org.png

だったのがstreamを使うと

avisynthcudafilters_20240413_stream_new.png

こんな感じで、同じ処理を表す緑の範囲が147usから94usに短縮できた。たしかにkernelを3並列で実行して、kernel切り替えの隙間を他のkernelで埋めることができ、同じ処理の実行時間が削減で来ていることがわかる。



4. kl_searchの一部の高速化



とはいえ、こうした高速化を積み上げてもやはり少しづつしか処理時間を削れず、限界はある…ということで、やはり一番遅いkl_searchを高速化したい。

kl_searchで一番重い関数は、dev_calc_sadで、いわゆる差の絶対値和を求める計算になっている。すでに__sadを使ってこれを高速に計算してる(内部命令ではvabsdiff)のだけど、まあとにかく実行回数が多い。実際、kl_searchで実行された命令をチェックしてみると5番目ぐらいにVABSDIFFが来ている。

avisynthcudafilters_20240413_kl_search_original_03.png

そこで、対象が8bitの場合、Ampere以降のGPUにはこれを4つ同時に実行してくれる命令(vabsdiff4)が追加された(というか復活した)ので、これを使ってみた。

avisynthcudafilters_20240413_kl_search_new_03.png

VABSDIFFがなくなって、代わりにVABSDIFF4が使われているけどかなり数は減っていて、計算負荷が下がったのがわかる。

さすがに重い関数だけあって効果は大きく、kl_searchの所要時間を大きく短縮することができた。




比較




環境
CPUi9 12900Ki7 11700K
Core8P+8E/24T8C/16T
RAMDDR4-3600DDR4-3600
GPURTX4080GTX1080
GPUドライバ551.23546.33
OSWin11 x64Win11 x64


Amatsukaze 0.9.6.3/0.9.7.0
エンコード: NVEnc 7.50 デフォルト (H.264)
デコード: デフォルト (CPU)
フィルタ設定: KFM(VFR)+SMDegrain+DecombUCF+Deblock
入力ファイル: ささこい #01 (1440x1080, 約30分)



Amatsukaze 0.9.6.3 (オリジナル @ RTX4080)



avisynthcudafilters_20240414_speed_0963_text.png



Amatsukaze 0.9.7.0 (高速化後 @ RTX4080)



avisynthcudafilters_20240414_speed_0970_text.png



高速化詳細



GTX1080の結果も追加して、高速化の内訳はこんな感じ。

avisynthcudafilters_20240414_speed.png

エンコードもデコードもボトルネックにならないような、高速化効果が出やすい条件を選んでいるのもあって、RTX4080ではそこそこの高速化になっている。原理的にはAmpere以降のGPUでそれなりに高速化するはず。

一番効果が大きいのが、「3-1. kernelの統合」というのも面白い。ひとつひとつは大したことがないけど、たくさん統合したので目に見える効果になったと思う。

一方、GTX1080については残念ながら少ししか高速化できていない。そもそもビルドしなおすと遅くなるのが謎である…。まあ最終的にはオリジナルより少しだけど高速化しているようでよかった(正直遅くなったときはどうしようかと思った)



ということで、中身のアルゴリズムはあまり理解していないけれど、プログラミング的な工夫である程度の高速化ができた。

AvisynthCUDAFiltersのビルドに挑戦し始めてからかなり時間が経ってしまったけど、目的だった高速化はひとまず達成できてよかった。



ダウンロード>>


コメントの投稿

非公開コメント

No title

ついにKFM高速化ですか!
KFMのビルド成功からのソース復元で、いつかは高速化していただけると密かに期待しておりましたが、想像以上に早くて驚きました。
これから、自分の環境で、どれくらい効果があるのか、試させていただきます。
いつも想像以上のバージョンアップを施してくださり、感謝しかありません。今後も、どうかよろしくお願いいたします。

速くなりすぎ

amatsukazeは使ってないのですが、中身のプラグインだけお借りしました。普段のエンコード時間が半分くらいになってびっくりです。高速化ありがとうございます。

No title

> supertoppo 様

こちらこそありがとうございます。
お使いのGPUや使用しているフィルタ、エンコーダの条件によっては、あまり効果がない場合もあるかもしれませんが、無事高速化できているとうれしいです。

> manta 様

コメントありがとうございます。
正直そこまで速くなるケースがあるとは思っていなかったので驚きですし、無事速くなってよかったです!

字幕消しについて

初めまして。お世話になっております。知識が乏しくお手数おかけいたします。
Amatsukaze についてご教示いただけると幸いです。
もともとある洋画の字幕は正常にエンコードされ重宝しております。
邦画で元映像には字幕がないのにAmatsukazeのエンコード後映像に日本語字幕が全編表示されます。(表示されないこともあります)
プロファイルに「字幕を無効にする」としても字幕が表示されます。
操作手順の間違いと思いますが、よろしくお願いいたします。
エンコーダ:QSVenc MPEG2デコーダ:CUVID H264デコーダ:CUVID
出力フォーマット:TS 出力選択:本編とCMを分離 フイルタ設定:フイルタなし 字幕を無効にする:チェック 並列ロゴ解析:チェック

Re: 字幕消しについて

字幕を無効にしても、字幕が表示されるのは謎ですね。

ただ、一般的な放送だと、日本語でも字幕(文字放送)のデータが入ってきていて、動画ファイルに自動で追加されています。

再生ソフト側で字幕の表示、非表示を切り替えられると思います。

MPC-BEでしたら、以下のサイトに説明があります。
https://kimama9.blog.fc2.com/blog-entry-867.html

お試しください。

Re: Re: 字幕消しについて

おそらくARIB字幕をass化したもののことかと思うのですが、いただいた条件では手元ではass/srt字幕はmuxされず、すみませんが原因がわからないです。

「字幕を無効」でよいはずなのですが…。

supertoppoさまがおっしゃっているとおり、まずは再生ソフト側での切り替えをお試しください。

字幕消しについて

お手数おかけしております。
EpgDataCap_Bonで録画し、Amatsukazeのバッチ処理でCMカット・ロゴ消しの流れで活用させていただいております。
MPC-BEなど再生ソフトで字幕は消えませんでした。映像上に字幕が埋め込まれていいるように思います。プロファイルの設定など見直ししてみたいと思います。大変ありがとうございました。

logエラー

ご参考まで、コンソールに以下のメッセージが残ります。

サブディレクトリまたはファイル V:\TS-Anime\encoded\メイン動画以外 は既に存在します。
ハンドルされていない例外: System.IO.FileLoadException: ファイルまたはアセンブリ 'AmatsukazeServer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'、またはその依存関係の 1 つが読み込めませんでした。操作はサポートされません。 (HRESULT からの例外:0x80131515) ---> System.IO.FileLoadException: ファイルまたはアセンブリ 'file:///C:\Program Files\EARTH SOFT\Amatsukaze\exe_files\AmatsukazeServer.dll'、またはその依存関係の 1 つが読み込めませんでした。操作はサポートされません。 (HRESULT からの例外:0x80131515) ---> System.NotSupportedException: ネットワーク上の場所からアセンブリを読み込もうとしました。これにより、以前のバージョンの .NET Framework で、アセンブリがサンドボックス化された可能性があります。このリリースの .NET Framework では、CAS ポリシーが既定で有効になっていないため、この読み込みは危険な場合があります。この読み込みがアセンブリのサンドボックス化を目的としない場合は、loadFromRemoteSources スイッチを有効にしてください。詳細については、http://go.microsoft.com/fwlink/?LinkId=155569 を参照してください。
--- 内部例外スタック トレースの終わり ---
場所 System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
場所 System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
場所 System.Reflection.RuntimeAssembly.InternalLoadFrom(String assemblyFile, Evidence securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm, Boolean forIntrospection, Boolean suppressSecurityChecks, StackCrawlMark& stackMark)
場所 System.Reflection.Assembly.LoadFrom(String assemblyFile)
場所 Amatsukaze.Command.ScriptCommand.<>c.<Main>b__2_0(Object _, ResolveEventArgs e)
場所 System.AppDomain.OnAssemblyResolveEvent(RuntimeAssembly assembly, String assemblyFullName)
--- 内部例外スタック トレースの終わり ---
場所 Amatsukaze.Command.ScriptCommand.CommandMain(String[] args)
場所 Amatsukaze.Command.ScriptCommand.Main(String[] args)

Re: logエラー

エラーメッセージを見る限り、exe_files\AmatsukazeServer.dllのファイルがブロックされて、ロードできていないように見えます。私自身経験ないので試したことはないのですが、exe_files内のdllファイルを右クリップしてブロックされているものがあれば、プロパティからブロックを解除すると改善するかもしれません。

それで改善しない場合、大変申し訳ありません、おっしゃっているエラー発生時の状況がつかめず、また最終的な問題がどういったものなのか把握できていないため、その他の改善方法を示すのは難しいです。Amatsukaze起動時、Amatsukazeでの処理開始時、チャプター・CM解析開始時、エンコード開始時、エンコード終了時など、いろいろなタイミングが考えられるのですが、具体的に、どのような状況でエラーが発生するのか、お教えいただきたく思います。

No title

いつも更新ありがとうございます。5950X+GTX1060という環境ですが少し高速化しています、GTX世代も切り捨てずに対応してくださってありがとうございます…!

話が変わり恐縮なのですが、1つ要望があります。
CM品質オフセットをx265ソフトウェアエンコードでも利用できるようにはできませんか…?CRFで指定しているところにビットレート倍率では破綻が目立ってしまったり、そのままだと本編とCMで分離して出力されたファイル容量CMの方が大きいこともままあるといった感じで…両方qp、CRFで設定できたらなと思っている次第です、ぜひ検討していただけましたら幸いです。

Re: No title

GTX1060での少し高速化できているとのことで安心しました!

CM品質オフセットやビットレート倍率についてですが、基本的にはCM部分の領域で分離するしないにかかわらずビットレートを下げるものだと思います。

x265では部分的にビットレートを下げる指定をzonesというオプションで行うのですが、これがcrfでの指定ができないのでCM品質オフセットに関しては対応できていません。

CMを分離というモードはほぼ使ったことがなくて詳しい動作を把握できていないですが、完全に分離してしまうのであればzonesでの指定は必要ないはずで、もしかするとできるかもしれませんので、考えてみたいと思います。

プラグインとしてなんですが

当方のGTX1660Tiではエンコーダーネックの様でAmatsukazeではほとんど速くなりませんでした。
他の方もされていましたがAvisynthNeoのプラグインとして使ったところKFMdeintのmode=0,3pass目がpreset=Fasterだけしか完遂しません。それ以外は応答しなくなります、AvsPmodでプレビューさせるとメモリーアクセス不良的なエラーメッセージが出ます。
元のではfaster以外でも、高速版もFasterでは完遂するので何とか動かす事が出来ないでしょうか。

QSVEncでエラー

はじめまして 大変ありがたく使わせてもらっていますがQSVEnc+tsreplaceで1/5くらいの割合で不正なオプションファイルが出来てエラーで終了します
0.9.6.7,と0.9.7.0 + Windows10
CMビットレート倍率 1.00 CM品質オフセット 0.00
でエンコして下記のようになります
AMT [info] "C:/ols/Enc/QSVEncC_x64/QSVEncC64.exe" --colorprim bt709 --transfer bt709 --colormatrix bt709 --tff --icq 23 --gop-len 90 --max-bitrate 7000 --vbv-bufsize 4000 --option-file "C:/Work/Amatsukaze/amt2630491/v0-0-0.opt.txt" --frames 50349 -o "C:/Work/Amatsukaze/amt2630491/v0-0-0.raw" --output-format mp4 --y4m -i -

v0-0-0.opt.txtの中身
--dynamic-rc 0:174,???=23
--dynamic-rc 2632:5329,???=23
--dynamic-rc 47827:48536,???=23
(icqが文字化け?)

正常な場合は空の v0-0-0.opt.txtが出来てQSVEncに--option-fileの指定はありません
--dynamic-rc、--option-fileを完全に無効化できないでしょうか

Re: Re: No title

なるほど、そういった事情があったのですね…

考えていただけるとのことで非常にありがたい限りです、ありがとうございます。
気長にお待ちしております。

No title

encoded 104034 frames, 190.02 fps, 2880.55 kbps, 596.00 MB


> ぺーさん さま

Amatsukazeの次のバージョンはもう少し先になりそうなのですが、KTGMCがfaster以外でフリーズしてしまう問題については、新しいCUDAでビルドしなおしたことによるものとわかり修正をすでに試みております。

ちょっとまだテスト中というところですが、一応最新バージョンは下記にあります。手元ではAmatsuakze経由で480iでテストしたので、Slowerは動作するようになったと思います。
https://nightly.link/rigaya/AviSynthCUDAFilters/actions/runs/8762497773/AviSynthCUDAFilters_Release_r279.zip

> フジヤマ2210 さま

ご指摘ありがとうございます。まだ原因調べられていないですが、今後調査して修正したいと思います。

残念ながら

早速の対応ありがとうございます。
最新バージョンでテストしましたが改善しませんでした。
Fasterは〇、slowerを含め他は×

Re: 残念ながら

テストいただきありがとうございます。

残念ながら改善しなかったこと承知いたしました。

すぐ可能かはわかりませんが、引き続き時間がある時に確認してみます。
プロフィール

rigaya

Author:rigaya
アニメとか見たり、エンコードしたり。
連絡先: [email protected]
github twitter

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

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

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

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

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

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

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

VVenCguiEx
- VVenCによるVVC出力
- VVenCguiExの導入>

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


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

clcufilters 
- OpenCL/CUDAのGPUフィルタ集
- 対応フィルタの一覧等はこちら

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

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

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

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

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

○その他
Amatsukaze改造版
- AmatsukazeのAV1対応版

tsreplace
- tsの映像のみを置き換えて圧縮

rkmppenc
- Rockchip系SoCのhwエンコーダ

fawutil
- FAW(FakeAACWave)⇔aac変換
- 二重音声の取り扱いにも対応

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