Vitis AI は、C++ および Python のサンプル デザインを提供し、統合されたクラウド/エッジ ランタイム プログラミング API の使用法を示します。
注記: サンプル コードは、ユーザーが新しいランタイム (VART) を使用できるようにサポートすることを目的としており、パフォーマンスのベンチマーク用ではありません。
統合された API に慣れるために、VART のサンプルを利用できます。これらのサンプルは、API を理解するためのものであり、高性能を実証するためのものではありません。これらの API はエッジとクラウド間で互換性がありますが、クラウド ボードにはバッチ処理などのさまざまなソフトウェア最適化があり、エッジではより高性能を実現するためにマルチスレッドが必要です。より高い性能を求める場合は、Vitis AI ライブラリのサンプルおよびデモ ソフトウェアへアクセスしてください。より高性能を追求するために最適化を実行する場合は、次のような推奨事項があります。
- スレッドのパイプライン構造を再配置して、すべての DPU スレッドに独自の「DPU」ランナー オブジェクトが含まれるようにします。
- DPU FPS が表示レートよりも高い場合には、表示スレッドを最適化して一部のフレームをスキップします。ビデオ表示に 200FPS は高過ぎます。
- 事前のデコード。ビデオ ファイルは H.264 でエンコードされている場合が多く、デコーダーは DPU よりも低速で、CPU リソースを大量に消費します。ビデオ ファイルは、あらかじめデコードして未加工の形式に変換しておく必要があります。
- Alveo ボード上のバッチ モードでは、ビデオ フレームにジッターが発生する可能性があるため、特に配慮する必要があります。ZCU102 ではバッチ モードをサポートしていません。
- OpenCV
cv::imshow
は低速であるため、libdrm.so
を使用する必要があります。これは、X サーバー経由ではなく、ローカル ディスプレイ専用です。
次の表では、これらの Vitis AI のサンプルについて説明しています。
ID | サンプル名 | モデル | フレームワーク | 説明 |
---|---|---|---|---|
1 | resnet50 | ResNet-50 | Caffe | Vitis AI の統合された C++ API を使用する画像分類。 |
2 | resnet50_pt | ResNet-50 | PyTorch | Vitis AI の統合された拡張 C++ API を使用する画像分類。 |
3 | resnet50_ext | ResNet-50 | Caffe | Vitis AI の統合された拡張 C++ API を使用する画像分類。 |
4 | resnet50_mt_py | ResNet-50 | Caffe | Vitis AI の統合された Python API を使用するマルチスレッドの画像分類。 |
5 | inception_v1_mt_py | Inception-v1 | TensorFlow | Vitis AI の統合された Python API を使用するマルチスレッドの画像分類。 |
6 | pose_detection | SSD、姿勢検出 | Caffe | Vitis AI の統合された C++ API を使用する姿勢検出。 |
7 | video_analysis | SSD | Caffe | Vitis AI の統合された C++ API を使用するトラフィック検知。 |
8 | adas_detection | YOLOv3 | Caffe | Vitis AI の統合された C++ API を使用する ADAS 検知。 |
9 | segmentation | FPN | Caffe | Vitis AI の統合された C++ API を使用するセマンティック セグメンテーション。 |
10 | squeezenet_pytorch | Squeezenet | PyTorch | Vitis AI の統合された C++ API を使用する画像分類。 |
Vitis AI の統合された C++ 高レベル API を使用してモデルを運用する際の一般的なコード スニペットを次に示します。
// get dpu subgraph by parsing model file
auto runner = vart::Runner::create_runner(subgraph, "run");
// get input scale and output scale,
// they are used for fixed-floating point conversion
auto outputTensors = runner->get_output_tensors();
auto inputTensors = runner->get_input_tensors();
auto input_scale = get_input_scale(inputTensors[0]);
auto output_scale = get_output_scale(outputTensors[0]);
// do the image pre-process, convert float data to fixed point data
// populate input/output tensors
auto job_id = runner->execute_async(inputsPtr, outputsPtr);
runner->wait(job_id.first, -1);
// process outputs, convert fixed point data to float data
Vitis AI の統合された拡張 C++ 高レベル API を使用してモデルを運用する際の一般的なコード スニペットを次に示します。
// get dpu subgraph by parsing model file
std::unique_ptr<vart::RunnerExt> runner =
vart::RunnerExt::create_runner(subgraph, attrs.get());
// get input & output tensor buffers
auto input_tensor_buffers = runner->get_inputs();
auto output_tensor_buffers = runner->get_outputs();
// get input scale and output scale,
// they are used for fixed-floating point conversion
auto input_tensor = input_tensor_buffers[0]->get_tensor();
auto output_tensor = output_tensor_buffers[0]->get_tensor();
auto input_scale = get_input_scale(input_tensor);
auto output_scale = get_output_scale(output_tensor);
// do the image pre-process, convert float data to fixed point data
setImageBGR(images[batch_idx], (void*)data_in, input_scale);
// sync data for input
input->sync_for_write(0, input->get_tensor()->get_data_size() /
input->get_tensor()->get_shape()[0]);
// populate input/output tensors
auto v = runner->execute_async(input_tensor_buffers, output_tensor_buffers);
auto status = runner->wait((int)v.first, -1);
// sync data for output
output->sync_for_read(0, output->get_tensor()->get_data_size() /
output->get_tensor()->get_shape()[0]);
// process outputs, conver fixed point data to float data
Vitis AI の統合された Python 高レベル API を使用してモデルを運用する際の一般的なコード スニペットを次に示します。
dpu_runner = runner.Runner(subgraph,"run")
# populate input/output tensors
jid = dpu_runner.execute_async(fpgaInput, fpgaOutput)
dpu_runner.wait(jid)
# process fpgaOutput
注記:
- VART については、サポートされる入力データの形式は fp32 と int8 です。
- DPU の入力と出力は NHWC 形式です。
- MPSoC 上の Softmax IP については、入力は int8 で出力は float32 です。
注記: DPU プロセスは、固定小数点データの入力および出力に対してのみ動作します。int8 データを入力として使用し、前処理および浮動小数点から固定小数点への変換を実行すると、性能とメモリ使用効率が向上します。入力データが浮動小数点の場合、VART によって浮動小数点データが固定小数点データへ変換されますが、これには時間がかかります。
注記: クオンタイザーのデフォルトの丸めモードは「HALF_UP」であるため、入力と出力を INT8 との間で変換する際は、同じ丸めモードを使用する必要があります。これにより、プリプロセス部分とポストプロセス部分がボード上でもサーバー上と同じように実行されます。ただし、性能と精度のバランスをとるために、入力と出力を INT8 との間で変換する際は通常は「切り捨て」を使用します。