グラフを実行する
Graph は計画図です。Run は、実際に実行するためのハンドルです。
グラフを作成した後に、このページを使用してください。グラフにどのノードまたはフラグメントを含めるかをまだ決定する必要がある場合は、グラフ から始めます。グラフがすでに適切な状態になっている場合は、このページで実行、処理、測定を行い、実際の入力に耐えられるようにします。
一度限りの実行か、再利用可能な実行かを選択してください。
そのジョブに最適な、最も短いランタイムパスを使用してください。
| 必要です | 使用する | なぜ |
|---|---|---|
| 1つの入力を行い、1つの出力を得る。 | Graph.run(...) | 最短の単一経路。 |
| 時間経過に伴い、多数の入力を送信する。 | Graph.build(...)とRun | ランタイムを再利用し、プッシュ/プル制御を可能にします。 |
| 名前付きの入力または出力を使用してください。 | Graph.build(...) と名付けられ、run.push(...) / run.pull(...) と呼ばれる。 | 複数の入力と出力を伴うアプリケーションを明確に定義します。 |
| ソースノードを起点としてグラフを生成する | アプリからの入力なしで、Graph.build() または Graph.run() を実行します。 | グラフがカメラ、ファイル、RTSP、またはその他のソースノードを所有している場合に利用します。 |
| 測定、エクスポート、排出、または意図的に停止する。 | Run | 製品のライフサイクルと診断機能を制御できます。 |
魔法は使わない。グラフを作成し、実行し、結果を確認する。
入力データがグラフにどのように入力されるかを選択してください。
キューを調整する前に、入力データの管理者を決定してください。
| グラフのスタイル | 入力がどのように行われるか | どのように実行するか |
|---|---|---|
| アプリからプッシュされるグラフ | お客様のアプリケーションは、Graph.run(input, ...)、run.run(input, ...)、run.push(...)、またはrun.try_push(...)のいずれかを呼び出します。 | 入力に基づいて構築または実行します。複数の入力を持つグラフに組み込む前に、エンドポイント名を確認してください。 |
| ソースが所有するグラフ | このグラフには、ファイル、カメラ、RTSP、またはストリーム入力などのソースノードまたはフラグメントが含まれています。 | アプリからの入力なしで構築または実行します:graph.build()またはgraph.run()。グラフに応じて、出力を取得したり、出力ノードを使用したり、コールバックを使用したりします。 |
グラフがソースを所有している場合は、そのグラフにデータを書き込まないでください。代わりに、グラフが出力する内容を調べてください。
ソースが所有するグラフを実行します。
グラフに独自のソースノードが含まれている場合は、アプリからの入力なしで、グラフを構築または実行してください。すでにソースノードを持つグラフにノードを追加しないでください。グラフが特定の出力を持つ場合、それらを出力として取り出します。グラフがシ ンクで終わる場合は、シンクノードが出力を処理するようにします。
入力と出力の両方をグラフが持つソースからシンクへのジョブには、graph.run()を使用します。アプリが結果を取り出したり、実行を計測したり、意図的に停止したりする必要がある場合は、graph.build()を使用します。
auto run = graph.build();
while (running && run.can_pull()) {
auto sample = run.pull("detections", /*timeout_ms=*/1000);
if (!sample) {
continue;
}
handle(*sample);
}
run.close();
長時間実行されるソースの場合、アプリケーションでループをいつ終了し、close() を呼び出すかを決定するようにします。タイムアウトとは、指定された時間内にデータが出力されなかったことを意味し、必ずしもソースの処理が完了したことを意味するわけではありません。
1回実行する
同期型のプッシュ/プル操作を 1 回だけ実行したい場合は、Graph.run(...) を使用してください。
simaai::neat::Graph graph("classifier");
graph.add(simaai::neat::nodes::Input("image"));
graph.add(model);
graph.add(simaai::neat::nodes::Output("classes"));
simaai::neat::TensorList outputs = graph.run(std::vector<cv::Mat>{frame});
Pythonでは、リストまたはタプルを渡します。graph.run([tensor])は、「バッチ次元を追加する」という意味ではなく、「1つのグラフ入力」を意味します。
再利用可能な実行環境を構築する
アプリケーションがループを所有している場合に、Graph.build(...) を使用してください。
auto run = graph.build();
run.push("image", std::vector<cv::Mat>{frame});
simaai::neat::TensorList outputs = run.pull_tensors("classes", /*timeout_ms=*/2000);
run.close_input();
while (auto sample = run.pull(/*timeout_ms=*/100)) {
// Drain remaining output after end-of-input.
}
run.close();
処理の完了と、実行中の作業の終了を希望する場合は、close_input() を使用してください。実行を中断したい場合は、close() を使用します。また、C++ では、即時停止を行うための関数として stop() が用意されています。
リクエスト/レスポンス処理に再利用可能な「Run」を使用してください。
Graph.run(...) は、最も短いワンショットパスです。毎回グラフを再構築することなく、同じリクエスト/レスポンスの形式を維持したい場合は、再利用可能な Run を一度作成し、run.run(...) を呼び出します。
以下の状況で使用します。
- グラフは、多数のリクエストの間も表示され続けます。
- 各リクエストは、それぞれが自身の出力結果を待つ必要があります。
- 現時点では、個別のプロデューサー スレッドとコンシューマー スレッドを用意する必要はありません。
auto run = graph.build();
for (const auto& frame : frames) {
simaai::neat::TensorList outputs = run.run(
std::vector<cv::Mat>{frame},
/*timeout_ms=*/2000);
handle(outputs);
}
run.close();
実行中の処理が必要な場合、またはプロデューサー/コンシューマーのスレッド、ノンブロッキングプッシュ、名前付き出力ポーリング、ドレイン制御が必要な場合は、run.run(...) から明示的な push(...) / pull(...) に移行します。