非同期推論要求

非同期推論要求は、デバイスのパイプライン構造に応じて、1 つまたは複数のタスク実行で推論パイプラインを非同期に実行します。OpenVINO ランタイムプラグイン API は、ov::IAsyncInferRequest 基本クラスを提供します。

  • このクラスには、std::vector<std::pair<std::shared_ptr<ov::threading::ITaskExecutor>, ov::threading::Task> >m_pipeline フィールドがあり、エグゼキューターと実行されたタスクのペアが含まれます。

  • すべてのエグゼキューターは引数としてクラスのコンストラクターに渡され、実行状態にあり、タスクを実行する準備ができています。

  • このクラスには、クラス・デストラクターで m_pipeline が終了するのを待機する ov::IAsyncInferRequest::stop_and_wait メソッドがあります。このメソッドはエグゼキューターを停止せず、タスク実行はコンパイルされたモデル・インスタンスに属して破棄されないため、まだ実行ステージにあります。

AsyncInferRequest クラス

OpenVINO ランタイムプラグイン API は、カスタム非同期推論要求の実装する ov::IAsyncInferRequest 基本クラスを提供します。

class AsyncInferRequest : public ov::IAsyncInferRequest {
public:
    AsyncInferRequest(const std::shared_ptr<InferRequest>& request,
                      const std::shared_ptr<ov::threading::ITaskExecutor>& task_executor,
                      const std::shared_ptr<ov::threading::ITaskExecutor>& wait_executor,
                      const std::shared_ptr<ov::threading::ITaskExecutor>& callback_executor);

    ~AsyncInferRequest();
    void cancel() override;

private:
    std::function<void()> m_cancel_callback;
    std::shared_ptr<ov::threading::ITaskExecutor> m_wait_executor;
};

クラスフィールド

  • m_cancel_callback - 実行を中断できるコールバック

  • m_wait_executor - デバイスタスクの完了に関するデバイスからの応答を待つタスク・エグゼキューター

プラグインがデバイスの複数のインスタンスで動作できる場合、m_wait_executor はデバイス固有である必要があります。そうしないと、複数のデバイスに単一のタスク・エグゼキューターを持たせると、それらを並行して動作できなくなります。

AsyncInferRequest()

AsyncInferRequest コンストラクターの目的は、デバイス・パイプライン m_pipeline を定義することです。以下の例は、次のステージでの m_pipeline の作成を示しています。

  • infer_preprocess_and_start_pipeline は、リモートデバイスにタスクを送信する CPU 軽量タスクです。

  • wait_pipeline は、リモートデバイスからの応答を待つ CPU 非計算タスクです。

  • infer_postprocess は CPU 計算タスクです。

ov::template_plugin::AsyncInferRequest::AsyncInferRequest(
    const std::shared_ptr<ov::template_plugin::InferRequest>& request,
    const std::shared_ptr<ov::threading::ITaskExecutor>& task_executor,
    const std::shared_ptr<ov::threading::ITaskExecutor>& wait_executor,
    const std::shared_ptr<ov::threading::ITaskExecutor>& callback_executor)
    : ov::IAsyncInferRequest(request, task_executor, callback_executor),
      m_wait_executor(wait_executor) {
    // In current implementation we have CPU only tasks and no needs in 2 executors
    // So, by default single stage pipeline is created.
    // This stage executes InferRequest::infer() using cpuTaskExecutor.
    // But if remote asynchronous device is used the pipeline can by splitted tasks that are executed by cpuTaskExecutor
    // and waiting tasks. Waiting tasks can lock execution thread so they use separate threads from other executor.
    constexpr const auto remoteDevice = false;

    m_cancel_callback = [request] {
        request->cancel();
    };
    if (remoteDevice) {
        m_pipeline = {{task_executor,
                       [this, request] {
                           OV_ITT_SCOPED_TASK(itt::domains::TemplatePlugin,
                                              "TemplatePlugin::AsyncInferRequest::infer_preprocess_and_start_pipeline");
                           request->infer_preprocess();
                           request->start_pipeline();
                       }},
                      {m_wait_executor,
                       [this, request] {
                           OV_ITT_SCOPED_TASK(itt::domains::TemplatePlugin,
                                              "TemplatePlugin::AsyncInferRequest::wait_pipeline");
                           request->wait_pipeline();
                       }},
                      {task_executor, [this, request] {
                           OV_ITT_SCOPED_TASK(itt::domains::TemplatePlugin,
                                              "TemplatePlugin::AsyncInferRequest::infer_postprocess");
                           request->infer_postprocess();
                       }}};
    }
}

ステージは次の方法で 2 つのタスク・エグゼキューターに分散されます。

  • infer_preprocess_and_start_pipeline は入力テンソルを準備し、CPU タスクを計算する m_request_executor 上で実行します。

  • CPU とプラグインが動作するリモートデバイスの計算タスクをオーバーラップするには、少なくとも 2 つのエグゼキューターが必要です。それ以外は、CPU とデバイスのタスクは 1 つずつシリアルに実行されます。

  • wait_pipeline は、デバイスと連携して動作する m_wait_executor に送信されます。

m_callback_executor もコンストラクターに渡され、ov::IAsyncInferRequest 基本クラスで使用されます。これにより、ユーザーが設定した callback_executor とコールバック関数のペアがパイプラインの最後に追加されます。

~AsyncInferRequest()

非同期要求のデストラクターでは、パイプラインの終了を待つ必要があります。これには、基本クラスの ov::IAsyncInferRequest::stop_and_wait メソッドを使用できます。

ov::template_plugin::AsyncInferRequest::~AsyncInferRequest() {
    ov::IAsyncInferRequest::stop_and_wait();
}

cancel()

このメソッドを使用すると、推論要求の実行をキャンセルできます。

void ov::template_plugin::AsyncInferRequest::cancel() {
    ov::IAsyncInferRequest::cancel();
    m_cancel_callback();
}