2016年8月10日水曜日

alloca vs vector

avisynthプラグインの書き方は人それぞれですが、一つの指標として次のようなものがあります。

AviSynth Plugin Writing Tips

これはAviSynth Wiki内に置かれたAvisynth+特設ページ内の記事ですが、特に書き慣れていない人、これからなにかしら書いてみたい人は一度は目を通しておくことをお勧めします。

軽く要約すると、
  • 例外は基本的に使わない。
  • 使う場合は発生時の処理もプラグインdll内で完結させる。上流(avisynth本体)に投げる場合はIScriptEnvironment::ThrowError()を必ず使うこと。

  • 自分でマルチスレッド処理を実装しないこと。
  • 特に最近のAvisynth+は単にGetFrame()を同時に複数実行するレベルではなく、全体的なバランスをとりつつキャッシュコントロールするレベルまで進歩しています(AvisynthMTとThreadRequestを両方実装したような感じかな)。 追加フィルタレベルでマルチスレッド化なんてやってもオーバーヘッドが増えるかデッドロック起こすだけで無駄に終わりますし、特にOpenMPの使用は(Avisynth+では)最悪手です。 シングルスレッドだとC++のみでは性能が出ない場合はSIMDを使うかGPUプログラミングに行くしかありません。

  • 使用するヘッダ(avisynth.h)はAvisynth+の最新のものを使うこと。
  • Avisynth+のヘッダはAvisynth本家の最新ヘッダと完全互換を謳っていますし、実際にそうなっています。特に64bit化を考えるならAvisynth+のものを使うしかありません。

で、それに続いてWriting better AviSynth pluginsという記事があります。


  • YUY2用のコードは書かない
  • メイン処理用関数はクラスメンバーにしない
  • memcpyの再実装はしない
  • Y,U,V各プレーンで同じ処理をする場合にコピペはしない

こちらも概ね正しいですが、一番最後のDon’t be afraid of allocaだけは参考にしない方がよいようです。

最近のコンパイラ(確認した限りではVS2013以降)であればstd::vectorを使うべきあり、もはやallocaを使う意義はまったくありません。

実際に私はallocaをstd::vectorに置き換えてみましたが、スピードはほぼ等速か、むしろstd::vectorのほうがほんの少し速かったです。

わざわざ初期化したり最後に個々の要素を開放したりは手間になるだけです。


ちなみにstd::vectorではなくnew/deleteで配列の確保/解放をしてみると、これも変わらないか若干vectorのほうが速い感じになりました。
どうやらC++においては動的配列の場合、_aligned_malloc/_mm_malloc以外はstd::vectorにしておくのが間違いがないようですね。



0 件のコメント:

コメントを投稿