OpenVINO™ ツールキット 2022.2 と oneAPI をベースとした GPU ビデオ解析パイプラインの構築 Part 1

インテル製の GPU デバイスで oneVPL と OpenVINO™ ツールキットを活用して簡単なビデオ解析パイプライン・サービスを構築する。

author-image

投稿者:

車両検出のタスクを例とした場合の AI ビデオ解析の一般的な手順は次のようになります。

  1. ビデオストリームのプルストリーム
  2. メディアデコード
  3. 画像の前処理でのスケーリング
  4. 深層学習推論ベースの車両識別
  5. 後処理フレーム
  6. メディアのエンコード・転送
  7. 解析結果の可視化

図: 汎用 AI ビデオ解析プロセス

エッジ・コンピューティング技術が進歩し AI 解析技術がエッジデバイスに搭載できるようになったことで、解析のリアルタイム性が向上し、ビデオストリーム転送のための帯域を抑えることが可能になってきています。この時点で、AI BOX エッジ・コンピューティング・デバイスは、メディアデータ分析のコアノードとして、IP カメラでエンコードされたビデオストリームのデータを直接読み取り、リアルタイムのデコードと推論を行い、結果データをバックエンド・ルームにプッシュします。その後、ビデオ監視装置と協力して、推論結果の後処理分析とアラームを完了します。また、後の確認できるように、エンコードされたイベント・キーフレームを保存します。

エッジ側の計算リソースが限られているため、このプロセスにおける性能のボトルネックは、AI BOX のビデオデコードや推理タスクで発生しがちです。また、システムのコストを考慮し、同じハードウェア・リソースを使用してより多くのビデオストリーム解析サービスを提供できるようにするため、この部分のプロセスをさらに最適化する方法は、今回の事例で共有する核心部分となります。

図: エッジ AI ビデオ分析アーキテクチャー

1. OpenVINO™ ツールキットの概要

深層学習処理に使われるインテル® ディストリビューションの OpenVINO™ ツールキットは、oneAPI を活用して開発された高性能な推論ライブラリーで、エッジからクラウドまでさまざまな インテルのプラットフォームで、実世界で起きていることを素早く、正確に解析するシステムの構築に貢献します。シンプルな開発ワークフローにより、OpenVINO™ ツールキットは、開発者が高性能アプリケーションとアルゴリズムを実現することを容易にします。

推論のバックエンドでは、OpenVINO™ ツールキットが実現する「Write once, deploy anywhere」の特性により、変換されたモデルはさまざまなインテル製のハードウェア・プラットフォームで実行することができ、ビルドと移行プロセスを効果的に簡素化できます。さらに、プラグイン式の開発アーキテクチャーを採用した OpenVINO™ ツールキットのランタイム API は、多くの異なるアクセラレーション・ユニットをサポートします。oneAPI の MKL-DNN、oneDNN などのアクセラレーション・ライブラリーにより、AVX-512 などの最新命令セットを活用したり、さまざまなハードウェア・アクセラレーターを活用することで、推論実行における全体的な推論モデル実行性能を向上させます。

また、OpenVINO™ ツールキットのバージョン 2022.2 では、インテルの最新のディスクリート GPU 製品 (dGPU) である、インテル® Arc™ グラフィックスをサポートしています。

2. OneAPI の概要

oneAPI は、オープンで標準化されたクロス・アーキテクチャー・プログラミング・モデルを提供し、さまざまなアーキテクチャー (CPU、GPU、FPGA、およびその他のアクセラレーターなど) にまたがるワークロードを活用した開発を可能にする開発ツールです。oneAPI には、クロスアーキテクチャー言語の Data Parallel C++ (ISO C++ および Khronos Group ベースの SYCL)、高度なライブラリー、およびコミュニティー拡張が含まれており、多くの企業、研究機関、大学でサポートされています。

oneAPI の重要なライブラリー・コンポーネントの 1 つである、oneVPL (インテル® oneAPI ビデオ・プロセッシング・ライブラリー) は、インテルの CPU、GPU などのハードウェアを活用したビデオデータのデコード、エンコード処理機能ライブラリーです。AVI、H.265 (HEVC)、H.264 (AVC)、MPEG-2、VP9 など、さまざまなメディア標準のハードウェア・デコード機能をサポートすることもできます。現在、oneVPL は次のタイプの GPU ハードウェアをサポートしています。
 

  • 第 11 世代インテル® Core™ プロセッサー内蔵 Xe アーキテクチャー搭載 GPU
  • インテル® Iris® Xe MAX シリーズ
  • インテル® Arc™ A シリーズ・グラフィックス
  • インテル® Data Center GPU Flex シリーズ
  • 今後発表される GPU プラットフォーム

インテルのハードウェア・コーデックでサポートできるビデオ・フォーマット形式の詳細については、以下をご参照ください。
Encode and Decode Capabilities for 7th Generation Intel® Core™ Processors and Newer

開発プロセス

このシステムはインテル製の GPU デバイスを使用してビデオを解析しています。主な理由は次のようになります。
 

  • 一般的に、性能と消費電力の面では、GPU 専用コーデックは CPU によるソフトウェア・デコードと比べてより強力なハードウェア・デコードを提供できます。入力ビデオの解像度が高いほど、ここでのパフォーマンスの差が大きくなります。
  • GPU デバイスの並列処理でのメリットにより、OpenVINO™ ツールキットは インテル最新の統合グラフィックス (iGPU) とディスクリート GPU (dGPU) を呼び出して推論する際にも、優れたスループット性能を発揮できます。
  • GPU 推論を呼び出すことで、インテル® アーキテクチャーのリソース使用率を最大限に高めることもできます。エッジ・コンピューティングにおけるタスクのアーキテクチャーでは、システムは画像レンダリング・サービスを処理するために GPU を必要とせず、CPU はより多くのリソース・スケジューリング作業を負担する必要があります。ビデオ解析タスクを CPU の統合グラフィックスに移行することで、この空きリソースを活用できるだけでなく、CPU の作業量を削減し、システムのコストをさらに最適化することができます。
     

そのため、ビデオストリーム解析の一環として、host との追加の転送オーバヘッドを回避するために、中間データを GPU のメモリーに「保持」できるようにする必要があります。これは「ゼロコピー」と呼ばれ、GPU の処理性能を最大化することができます。

図: GPU によるビデオ解析パイプライン

今回の例では、入力データは H.265 のビデオファイルを使用します。パイプライン全体を次の 4 つの部分に分けることができます。それぞれ oneVPL と OpenVINO™ ツールキット内の異なるコンポーネント・インタフェースに対応しています。

1. ビデオデコード (Libva)

oneVPL は Libva に依存しています。VA-API (Video Acceleration API) インターフェイスの上位層パッケージにより、GPU ハードウェア・コーデック能力を実現しました。この例では、デコード部分を次の手順により抽象化することができます。

まず、MFXVideoDECODE_Init インターフェイスを使用して、oneVPL session によりデコードモジュールを初期化します。

sts = MFXVideoDECODE_Init(session, &mfxDecParams);

次に、ビデオストリームを読み取り、stream buffer にカプセル化します。

sts = ReadEncodedStream(bitstream, source);

そして、MFXVideoDECODE_DecodeFrameAsync インターフェイスを呼び出してデコードタスクを実行し、デコードされたデータを pmfxDecOutSurface アドレスに書き込みます。

sts = MFXVideoDECODE_DecodeFrameAsync(session,
        (isDrainingDec) ? NULL : &bitstream,
         NULL,
         &pmfxDecOutSurface,
         &syncp);

2. 画像のスケーリング (VPP)

次に、oneVPL の VPP (Video processing functions) モジュールを使用して画像のスケーリング処理を行います。まず、出力画像のカラーチャネルやスケーリングされた画像サイズなど、いくつかのパラメータを定義する必要があります。ここでは、エンコード出力と推論入力のゼロコピー共有を実現するために、出力のカラー形式を NV12 に設定する必要があります。

mfxVPPParams.vpp.Out.FourCC = MFX_FOURCC_NV12;
mfxVPPParams.vpp.Out.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
mfxVPPParams.vpp.Out.Width = ALIGN16(vppOutImgWidth);
mfxVPPParams.vpp.Out.Height = ALIGN16(vppOutImgHeight);

次に、MFXVideoVPP_Init インターフェイスを使用して、VPP モジュールを初期化します。

sts = MFXVideoVPP_Init(session, &mfxVPPParams);

デコードされた出力データアドレスを MFXVideoVPP_ProcessFrameAsync インターフェイスに送信し、画像スケーリングを行い、指定したカラーチャネルで出力します。

MFXVideoVPP_ProcessFrameAsync(session, pmfxDecOutSurface, &pmfxVPPSurfacesOut);

3. 色空間とデータレイアウト変換 (OpenVINO™ Preprocessing API)

Preprocessing API は、OpenVINO™ ツールキット 2022.1 で新しく追加された機能です。通常の前処理操作の一部をノードとして実行時モデルに埋め込むことで、この部分の計算プロセスも指定されたハードウェア・プラットフォームにオフロードすることができます。同時に、OpenVINO™ ツールキットの強力なモデル加速能力を活用して、前処理タスクの性能を向上させることができます。ここでサポートできる前処理タスクは、次のようになります。
 

  • 精度変換: U8 buffer to FP32
  • Layout 変換: Transform to planar format: from {1, 480, 640, 3} to {1, 3, 480, 640}
  • Resize: 640x480 to 224x224
  • 色空間変換: BGR -> RGB
  • Normalization: mean/scale

図: Preprocessing API 機能の概略図

ここでは、VPP でサポートされていないいくつかの前処理演算子を Preprocessing API を使用して GPU で実行する一方で、CPU への負荷を減らすことができます。また、追加の Device to Host メモリー・コピーを回避することもできます。Open Model Zoo による事前学習モデルの説明から、本例で使用された車両検出モデルの入力データーチャネル要件が BGR で、データレイアウトが NCHW であることがわかります。従って、Preprocessing API を呼び出す場合は、次の 2 つの形式の変換をする必要があります。

図: vehicle-detection-0200 モデル入力要件の説明

コードに戻ります。pre_post_process ヘッダーファイルでの対応する関数を呼び出して、VPP 出力データの色空間変換 (YUV->BGR) とレイアウト変換 (NHWC->NCHW) をします。最後に build メソッドを使用して、前処理タスクを元のモデルの実行図に統合し、新しい model オブジェクトを生成します。

auto p = PrePostProcessor(model);
p.input().tensor().set_element_type(ov::element::u8)
        // YUV images can be split into separate planes
      .set_color_format(ov::preprocess::ColorFormat::NV12_TWO_PLANES, {"y", "uv"})
      .set_memory_type(ov::intel_gpu::memory_type::surface);
// Change color format
p.input().preprocess().convert_color(ov::preprocess::ColorFormat::BGR);
// Change layout
p.input().model().set_layout("NCHW");
model = p.build();

ここで、NV12 は Y と UV の 2 つのコンポーネントに分けられます。NCHW の変換をしない場合、チャネル・ディメンションが一致しないため、実行時にエラーが発生します。

4. モデル推論 (OpenVINO™ ツールキット・ランタイム)

ゼロコピーを実現するために、この例で OpenVINO™ ツールキットの「Remote Tensor API of GPU Plugin」関連のインターフェイスを使用します。これによって、VA-API コンポーネントとの GPU メモリー内にあるビデオデータの共有を実現します。具体的なステップは次のようになります。

まず、GPU で共有メモリーのコンテキストを作成します。

auto shared_va_context = ov::intel_gpu::ocl::VAContext(core, lvaDisplay);

次に、VPP 出力結果へのハンドルを取得します。create_tensor_nv12 インターフェイスを通じて、VA-API surface を OpenVINO™ ツールキットの tensor メモリー・オブジェクトに変換・カプセル化します。

lvaSurfaceID = * (VASurfaceID *) lresource;

// Wrap VPP output into remoteblobs and set it as inference input
auto nv12_blob = shared_va_context.create_tensor_nv12(height, width, lvaSurfaceID) ;

メモリー・オブジェクトを推論要求にロードして、推論を実行します。

infer_request.set_tensor(new_input0->get_friendly_name(), nv12_blob.first);
infer_request.set_tensor(new_input1->get_friendly_name(), nv12_blob.second);
                    
// start inference on GPU
infer_request.start_async();
infer_request.wait();

元のモデルとは異なり、入力データは 2 つになることがわかります。その理由は前のステップで、Preprocessing API を呼び出すとき、NV12 を Y と UV の 2 つの成分に戻したことにあります。従って、元のモデルの入力データの数もそれに応じて調整しなければなりません。

サンプルプログラムの使用方法

この例は、Ubuntu 20.04、第 11 世代インテル® Core™ プロセッサー内蔵 GPU および dGPU であるインテル® Arc™ A380 グラフィックス環境で検証されています。

1. サンプルプログラムのダウンロード

$ git clone https://github.com/OpenVINO-dev-contest/decode-infer-on-GPU.git

2. 対応するコンポーネントと依存関係をインストール

次の Github にある README ドキュメントを参照して、環境のインストールを行います。
https://github.com/OpenVINO-dev-contest/decode-infer-on-GPU

3. 事前学習モデルをダウンロード

この例では、Open Model Zoo の vehicle-detection-0200 モデルを使用して、ビデオストリーム内の車両を検出します。具体的なダウンロード・コマンドは次のとおりです。

$ omz_downloader –name vehicle-detection-0200

4. 推論タスクをコンパイルして実行

$ mkdir build
$ cd build
$ cmake -DCMAKE_BUILD_TYPE=Release ..
$ cmake --build .
$ ./single_src/single_source -i ../content/cars_320x240.h265 -m ~/vehicle-detection-0200/FP32/vehicle-detection-0200.xml

5. 出力結果

最終的な結果は次のようになります。

libva info: VA-API version 1.12.0
libva info: Trying to open /opt/intel/mediasdk/lib64/iHD_drv_video.so
libva info: Found init function __vaDriverInit_1_12
libva info: va_openDriver() returns 0
Implementation details:
  ApiVersion:           2.7  
  Implementation type:  HW
  AccelerationMode via: VAAPI
  Path: /usr/lib/x86_64-linux-gnu/libmfx-gen.so.1.2.7

この例では、各フレームの画面で検出された車両の信頼度や、画面内の座標情報などが出力されます。

まとめ

oneAPI の oneVPL コンポーネント、OpenVINO™ ツールキットの Preprocessing API と remote tensor インターフェイスを使用して、インテル製 GPU のハードウェア・ユニットで、デコード、前処理、推論といったビデオ解析の全プロセスを実行する、アプリケーションを構築できます。さらに、追加のメモリーコピーなしで、GPU リソースの使用率を大幅に向上できます。今後インテル製のディスクリート GPU シリーズ製品がリリースされるにつれて、今回のようなリファレンス・デザインを参考に、開発者が GPU プラットフォーム上でより良い性能を実現できることを期待しています。

OpenVINO™ ツールキット 2022.2 と oneAPI をベースとした GPU ビデオ解析パイプラインの構築 Part 2 へ