スレッディングモデル
アクティブな Run は、フレームワークとランタイムのスレッド上で処理を実行します。アプリケーションはこれらのスレッドを管理する必要はありませんが、独自のプッシュ、プル、コールバック、およびシャットダウンコードを適切に管理する必要があります。
スレッドの概要
一般的な Run の場合:
| スレッド | 役割 | 所有者 |
|---|---|---|
| GStreamer ストリーミングスレッド | ソース、変換、シンクのパスを介してバッファを移動します。 | GStreamer ランタイム |
| MLA ディスパッチャースレッド | MLA 処理を送信し、完了を収集します。 | Neat ランタイム |
| EV74 / CVU ディスパッチャースレッド | CVU 側のカーネルを送信し、完了をポーリングします。 | Neat ランタイム |
| プル側の待機スレッドとバス監視スレッド | 出力サンプルをパブリックキューに移動し、ランタイムエラーを報告します。 | Neat ランタイム |
| アプリケーションスレッド | Graph.build(...)、Graph.run(...)、Run.push(...)、Run.pull(...)、Run.stop()、またはコールバックを呼び出します。 | アプリケーション |
グラフフラグメント、ソースノード、およびシンク ノードは、ランタイム処理を追加できますが、ルールは変わりません。パブリックな Run は、アプリケーションが制御するハンドルです。
アプリケーションコードが実行される場所
ユーザーコードは、次の場所に存在します。
- 直接 API 呼び出し:
build(...)、run(...)、push(...)、try_push(...)、pull(...)、close_input()、stop()、およびclose()は、それらを呼び出すアプリケーションスレッドで実行されます。 - ドロップコールバック:
RunOptions.on_input_dropは、プッシュパスで実行されます。短く保ち、カウントして戻ります。 - テンソルコールバック:
Graph::set_tensor_callback(...)は、C++ のコールバックスタイルの処理です。コールバックを短く保ちます。時間がかかる処理は、ランタイムパスにバックプレッシャーを与えます。 - カスタムノードの説明: パブリックノードの構築とグラフの構成は、ビルド時にアプリケーションスレッドで行われます。
コールバックに時間がかかる処理を隠さないでください。コールバックで多くの処理を行う必要がある場合は、サンプルを独自のキューに渡し、戻ります。
ロックルール
Graph、Run、Tensor、および Sample を、APIでそうでないことが明示されていない限り、単一の所有者オブジェクトとして扱います。
サポートされているパターン:
- 1つのプロデューサースレッドが
push(...)またはtry_push(...)を呼び出します。 - 1つのコンシューマースレッドが
pull(...)を呼び出します。 - 別のコーディネータースレッドが、シャットダウン中に
stop()を呼び出す場合があります。
リスクのあるパターン:
- 複数のプロデューサースレッドが、ロックなしで同じ
Runにプッシュします。 - 複数のコンシューマースレッドが、明確な所有権ルールなしに同じ出力からプルします。
- コールバックが同じ
Runにコールバックし、さらに処理を待ちます。
複数のプロデューサーが必要な場合は、Run.push(...) を呼び出す前に、アクセスをシリアライズします。複数のコンシューマーが必要な場合は、1つのスレッドが Neat からプルした後、処理を分散します。
シャットダウンとキャンセル
意図に合ったシャットダウンプリミティブを使用します。
| 意図 | 使用 |
|---|---|
| 最後の入力の後、キューに登録された処理を完了する | run.close_input()、次に、出力がなくなるか、PullStatus::Closed が返されるまでプルします。 |
| 現在の処理を停止し、待機中の処理を解放する | run.stop() |
| ランタイムリソースを解放する | run.close() または、Run オブジェクトのスコープを終了させます。 |
stop() はキャンセル処理の経路です。キャンセル後、処理中のプルはブロック解除され、プッシュは停止する必要があります。処理が終了しようとしているランタイムにプッシュし続けないでください。
スループットスレッドの構成
アプリがプッシュするライブグラフや高スループットグラフの場合、まず2つのアプリケーションスレッドから始めます。
- プロデューサースレッドは、入力を読み込み、
stream_id/frame_idをスタンプし、選択したOverflowPolicyに従ってtry_push(...)またはpush(...)を呼び出します。 - コンシューマースレッドは、継続的にプルし、ランタイムによってバックアップされたバッファーが固定される前に、出力を解放またはコピーします。
独自のキューを中心に、同じ Run オブジェクトを中心に、より多くのアプリケーションスレッドを追加します。ホットループを単調にします。単調な処理は高速です。
関連資料
- グラフを実行する — ランタイムのライフサイクル、スループット、測定、およびバックプレッシャー。
Run— パブリックランタイムオブジェクト。- 非同期と同期のタイミングモデル — 処理がいつ行われ、呼び出しがいつ戻るか。