GPU の動き予測ハードウェアをOpenCLから使う

最近のGPUは、動画エンコーダを実装しているものが多いです。

Intel社のGPUは、この動画エンコーダで使われる、ブロック単位での動き予測ハードウェアを、OpenCLから使うことができます。

公式の解説 : https://software.intel.com/en-us/articles/intro-to-motion-estimation-extension-for-opencl

公式のサンプル : https://software.intel.com/en-us/articles/video-motion-estimation-using-opencl

公式のサンプルに気付かないで作ってしまったサンプル : https://bitbucket.org/fixstars/blog/src/95aecef11221e15d291076f815e171a4c7671e35/me/?at=master

手順は以下のとおりです。

clGetExtensionFunctionAddressForPlatform で、 “clCreateAcceleratorINTEL” のポインタを取得します。これは、デバイスが “cl_intel_accelerator” 拡張を持っているときに有効です。

これを使って、cl_accelerator_intel を作ります。

me_block_typeでブロックサイズを決めます。me_search_path_type で探索範囲を決めます。subpixel_mode は hpel, qpel などが選べるようです。sad_adjust_mode はすいません、よくわかりませんでした。普通にSADの場合は上のようにすればよいと思います。

block_motion_estimate_intel カーネルを作ります。

cl.hpp を使っているのでわかりづらいですが、OpenCL 1.2には、こういう特殊なカーネルを作る場合のために、 clCreateProgramWithBuiltInKernels というのがあります。これを使っています。

カーネルに引数を設定します。block_motion_estimate_intelカーネルの引数は、

と、なっていてそれぞれ、

  • accelerator : clCreatAccelerator で作ったもの (in)
  • src_image : 画像 (in)
  • ref_image : 参照画像 (in)
  • prediction_motion_vector_buffer : 予測ベクタ(探索開始位置にオフセットを付けます) (in optional)
  • motion_vector_buffer : 結果。ブロックあたり、 小数部2bitの符号付き16bit固定小数値が(column,row)のふたつ入ります。 (out)
  • residuals : SAD で出た差分 (out optional)

です。

時間を計測したところ、720p で 1.5~3.5[msec] 程度のようです。

簡単に書いた C++(OpenMPあり)だと、i7-4700MQ(2.4GHz 4core 8thread)で 65msecなので、それより20~40倍ぐらい速いですね。SADのBMはSIMDで速くなるのであまり良い比較ではないですが、さすがに20倍にはならないので、速いと言っていいと思います。

Atomのように小さいCPUだとより使うメリットは大きいですね、Atom Z3740 では 720p で、7[msec]程度で実行できるようです。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です