低レベル実装の詳細

CPU のスループット: 内部処理

スループット関連のセクションで説明したように、OpenVINO ストリームは複数の要求を並行して実行する手段です。同時に実行される複数の推論要求に最適に対応するため、推論スレッドは特定の CPU コアにグループ化/固定され、“CPU” ストリームを構成します。これにより、特にマルチコアシステムでは、バッチ処理よりもネットワークのパフォーマンスが大幅に向上します。

従来のアプローチ

ストリーム

すべての CNN 操作は内部で CPU コアすべてで並列化され、スケーラブルではない操作には悪い影響を及ぼします。
多くのスレッド間で大量の同期を行うと、オーバーヘッドが発生します。
効率を向上する唯一のオプションはバッチ処理です。
CPU コアは実行ストリーム (各 1 ~ 4 スレッド) に均等に分散されます。
ストリームあたりのスレッド数が少なくなると、同期が減少し、局所性が向上して、粒度が細かくなります。

conventional-approach

execution-streams
要求は少数のスレッドで並行して実行されます。
レイヤーに関しては、ストリームは同期の必要性を大幅に減らします。

バッチ処理と比較すると、並列処理は多少転置されています (入力に対して実行され、CNN 操作内での同期が大幅に減少します)。

大規模バッチアプローチ

ストリーム

すべてのスレッドはすべての入力を一度に処理します。
すべてのレイヤーが適切に並列化されていると仮定します。
“ファット (複雑)” な要求は 1 つずつ実行されます。
CPU コアは実行ストリーム間で均等に分散されます。
“最も外側のループを並列化する” のが経験則です。
個々の要求は並行して実行されます。

large-batch-approach

execution-streams-2
入力に関しては、ストリームは “転置された” バッチです。

高レベルのパフォーマンスのヒントにより、モデルの計算需要と CPU 能力 (int8 推論ハードウェア・アクセラレーション、コア数など) に応じて、実装に最適なストリーム数を選択できます。

自動バッチ処理の内部

自動バッチ処理は、推論要求をオンザフライでグループ化して、デバイスの使用率を向上させます。これにより、アプリケーションが大規模なバッチを “明示的に” 使用することで 、GPU などのデバイスを飽和させる要件が緩和されます。ユーザーにプログラミングの労力を課すことなく、個々の推論要求からの透過的な入力収集と、それに続く実際のバッチ実行が行われます。

../../../_images/batch_device.svg

基本的に、自動バッチ処理は、非同期性を個々の要求からバッチを構成する要求のグループに移行します。さらに、実行を効率良く行うには、バッチ処理のタイムアウトを発生させずに、要求がタイムリーに到着することが重要です。通常、タイムアウトに達することはありません。これは、アプリケーションの終了 (入力が到着しないため、バッチを収集できない場合) を処理する適切な方法です。

ワークロードでタイムアウトが発生し、すべての要求のレイテンシーが増加することでパフォーマンスが低下する場合、その値とバッチサイズのバランスを検討してください。例えば、すべての要求に対応することが保証できない大きなバッチサイズとタイムアウト値の組み合わせよりも、小さいバッチサイズとタイムアウト値のほうが良い結果が得られる可能性があります。

最後に、一般的な最適化get_tensor イディオムのセクションに従うことで、自動バッチ処理で入力/出力のコピーを軽減できます。それによると、アプリケーションでは常にテンソルのデータアクセス API の “get” バージョンを優先する必要があります。