ホームページ > 記事 > テクノロジー周辺機器 > スループットが 30 倍に向上: CV パイプラインがフルスタック並列化に移行
スタンフォード大学の教授であり、Tcl 言語の発明者でもある John Ousterhout は、かつて「ソフトウェア設計の哲学」という本を書き、その一般原則を体系的に論じました。ソフトウェア設計と方法論の本全体の核心は、「ソフトウェア設計の核心は複雑さを軽減することである」ということです。
実際、この観点は、基礎となるハードウェアの適応を伴うソフトウェア設計にも当てはまります。
ビジュアル モデル開発を例に挙げると、これまでのビジュアル モデル開発プロセスでは、速度と効果を向上させるためにモデル自体の最適化に重点が置かれていました。しかし、人々は画像の前処理(前処理)と後処理の段階にはほとんど注意を払いません。
モデルの計算、つまりモデルのトレーニングと推論の主要な段階がますます効率的になると、画像の前処理段階と後処理段階が画像処理タスクのパフォーマンスのボトルネックになります。
具体的には、従来の画像処理プロセスでは、前処理部分と後処理部分は通常、これにより、プロセス全体のワークロードの 50% から 90% 以上が前処理と後処理に関連することになり、アルゴリズム プロセス全体のパフォーマンスのボトルネックになります。
上記の問題は現在市場に出回っています。アプリケーション シナリオの CV ライブラリでは、基盤となるハードウェアに依存する一貫性の欠如が複雑さとパフォーマンスのボトルネックにつながります。 John Ousterhout が複雑さの原因を要約したように、複雑さは依存関係から生じます。
主流の画像処理ライブラリ OpenCV とその応用シナリオです非常に普及していますが、実際の使用にはいくつかの問題もあります。
たとえば、CPU バージョンの OpenCV を使用して最初にトレーニングを行ってから推論を行う場合、推論段階でより高いパフォーマンスのバージョンが必要になる場合があります。 トレーニング シナリオでは、前後の処理とモデルの推論を時間内にカバーできるため、前処理の時間をカバーできます。ただし、推論パイプラインでは、モデルには前方推論のみが含まれており、Tensor RT 高速化後は消費時間が大幅に削減されますが、このとき、前処理の消費時間は非常に大きくなり、これをカバーするのは困難です。モデル推論。 推論シナリオの時間を短縮し、パフォーマンスを向上させるために、一般に、GPU バージョンの OpenCV が高速化に使用されます。 ただし、OpenCV の CPU バージョンと GPU バージョンの間で結果が一致しない可能性があります。典型的な例は、CPU バージョンと GPU バージョンの差を異なる方法で計算するサイズ変更オペレーターです。 OpenCV は、トレーニング中と推論中に異なるバージョンのオペレーターを使用します。トレーニング中は、CPU オペレーターの適用範囲が比較的高いため、一般に CPU が使用されます。推論中は、パフォーマンスが比較的高いため、GPU が一般的に使用されます。良好です。したがって、これにより結果の位置合わせに問題が発生する可能性もあります。つまり、モデルのトレーニングに CPU を使用し、モデルの推論に GPU を使用する場合、最終的な出力結果は一致しません。 第二に、一部の GPU オペレーターのパフォーマンスが低下します。 OpenCV では、一部の GPU オペレーター自体が比較的時間がかかるため、オペレーター全体のパフォーマンスが低下し、CPU バージョンよりもさらに悪くなります。 第三に、OpenCV の GPU オペレーターの対象範囲は限られており、一部のオペレーターは CPU バージョンしか持っていません。また、一部の GPU オペレーターでは、パラメータやデータ型などのカバー範囲が CPU バージョンほど高くなく、使用に制限が生じます。 最後に、使用中に CPU オペレーターと GPU オペレーターを対話的に使用すると、CPU と GPU の間で大量のデータのコピーと同期操作が発生し、全体的な加速性能が不十分になります。 もう 1 つの一般的に使用される画像処理ライブラリは、TorchVision です。TorchVision モデル推論を行う場合、一部のオペレーターには C インターフェイスが不足しているため、呼び出し時に柔軟性が欠如します。 C バージョンを生成したい場合は、TorchScript 経由で生成する必要があります。インタラクティブに使用するためにプロセスの途中で他のライブラリから演算子を挿入すると、余分なオーバーヘッドと作業負荷が発生するため、使用時に大きな不便が生じます。 TorchVision のもう 1 つの欠点は、オペレーターのカバー率が高くないことです。
上記は、現在の主流の CV ライブラリの制限です。
前処理と後処理のパフォーマンスのボトルネックは主に次の点にあります。 CPU 計算の使用とモデル コンピューティング段階で GPU を使用するテクノロジーはますます成熟してきています。
#したがって、自然な解決策は、GPU を使用して前処理と後処理を高速化することです。これにより、アルゴリズム パイプライン全体のパフォーマンスが大幅に向上します。
この目的を達成するために、NVIDIA と ByteDance は共同で画像前処理オペレーター ライブラリ CV-CUDA をオープンソース化しました。 CV-CUDA は GPU 上で効率的に実行でき、オペレーターの速度は OpenCV の約 100 倍に達します。
2023 年 1 月 15 日、9:30 から 11:30 まで、NVIDIA が主催する「CV-CUDA ファースト オープンクラス」に、NVIDIA、ByteDance、Sina Weibo の技術専門家から 3 名の受講生 (Zhang Yi、 Sheng Yiyao 氏、Pang Feng 氏) は関連トピックについて詳しく共有しており、この記事では 3 人の専門家の講演の要点を要約します。
CPU の代わりに GPU を使用すると、多くの利点があります。まず、前処理演算子と後処理演算子が GPU に移行された後、演算子の計算効率を向上させることができます。
第二に、すべての処理がGPU上で実行されるため、CPUとGPU間のデータコピーが削減できます。
最後に、CPU 負荷を GPU に移行すると、CPU 負荷が軽減され、複雑なロジックを必要とする他のタスクの処理に CPU を使用できるようになります。
プロセス全体を GPU に移行すると、パイプライン全体が 30 倍近く改善され、コストを節約できます。コンピューティングのオーバーヘッドを削減し、運用コストを削減します。
図のデータ比較から、同じサーバーとパラメーター構成の下で、OpenCV は最大 2 ~ 3 の 30fps 1080p ビデオ ストリームを開くことができることがわかります。並列ストリームの場合、PyTorch (CPU) は最大 1.5 個の並列ストリームを開くことができますが、CV-CUDA は最大 60 個の並列ストリームを開くことができます。全体的なパフォーマンスの向上が非常に大きいことがわかります。関係する前処理演算子にはサイズ変更、パディング、正規化などが含まれ、後処理演算子にはクロップ、サイズ変更、合成などが含まれます。
なぜ GPU が事前の高速化ニーズに適応できるのかそして後処理? モデル計算と前処理および後処理間の非同期の利点を活用し、GPU の並列コンピューティング機能に適応します。
私たち前処理モデルトレーニングとモデル推論の非同期については個別に説明します。
PyTorch や TensorFlow など、現在の主流の機械学習フレームワークは、データの準備とモデルの計算が非同期です。 PyTorch を例に挙げると、データ準備のために複数のサブプロセスが開始されます。 図に示すように、モデル計算とデータ準備という 2 つの状態が含まれており、両者の間には時系列の関係があります。 D0 が完了したら、B0 に進むことができます。 #パフォーマンスの観点からは、データ準備の速度がモデルの計算の速度に追いつくことが期待されます。ただし、実際の状況では、一部のデータ読み取りおよびデータ前処理プロセスに時間がかかり、対応するモデル計算が実行されるまでに一定のウィンドウ期間が発生し、GPU 使用率が低下します。 データ準備は、データ読み取りとデータ前処理に分けることができ、これら 2 つの段階は、PyTorch フレームワークなどで直列または並列で実行できます。シリアルに実行されます。 データストレージメディア、ストレージ形式、並列処理、実行プロセス数など、データ読み取りのパフォーマンスに影響を与える要因は数多くあります。 対照的に、データ前処理のパフォーマンスに影響を与える要素は比較的単純で、並列度です。並列度が高くなるほど、データ前処理のパフォーマンスが向上します。つまり、データ前処理とモデル計算を非同期化し、データ前処理の並列性を高めることで、データ前処理のパフォーマンスを向上させることができます。 2. モデル推論の非同期の前処理
In Inモデル推論フェーズでは、そのパフォーマンスには 2 つの指標があります。1 つ目はスループット、2 つ目は遅延です。ある程度まで、これら 2 つの指標は相互に排他的です。
単一クエリの場合、サーバーはデータを受信した後、データを前処理してからモデル推論を実行します。したがって、単一のクエリの場合、それはある程度シリアルなプロセスになります。
しかし、これは非常に非効率的であり、多くのコンピューティング リソースを無駄にします。スループットを向上させるために、多くの推論エンジンはトレーニング フェーズと同じ戦略を使用して、データとモデルの計算を非同期に準備します。データ準備フェーズでは、一定量のクエリが蓄積されてバッチに結合され、その後の計算が実行されて全体のスループットが向上します。
スループットの点では、モデル推論とモデル トレーニングは比較的似ています。データ前処理ステージを CPU から GPU に移動することで、スループットの向上を実現できます。
同時に遅延の観点から見ると、クエリ文ごとに前処理の時間を短縮できれば、その分クエリごとの遅延も短くなります。
モデル推論のもう 1 つの特徴は、逆方向の計算ではなく順方向の計算のみを行うため、モデルの計算量が比較的少ないことです。これは、モデル推論には高度なデータ前処理が必要であることを意味します。
計算に十分な CPU リソースがあると仮定すると、理論的には前処理がパフォーマンスのボトルネックになることはありません。パフォーマンスが追いつかないことがわかったら、前処理操作を行うプロセスを追加するだけで済むためです。 したがって、CPU リソースの競合が発生した場合にのみ、データの前処理がパフォーマンスのボトルネックになる可能性があります。
実際のビジネスでは、CPU リソースの競合が非常に一般的であり、これにより後続のトレーニングおよび推論段階での GPU 使用率が低下し、トレーニング速度が低下します。
GPU のコンピューティング能力が向上し続けるにつれて、データ準備フェーズの速度要件がますます高くなることが予測されます。
このため、CPU リソースの競合の問題を軽減し、GPU の使用率を向上させるために、前処理部分を GPU に移動するのは自然な選択です。
全体として、この設計はシステムの複雑さを軽減し、モデル パイプラインの本体を GPU に直接適応させるため、GPU と CPU の両方の使用率を向上させるのに大きく役立ちます。同時に、異なるバージョン間の結果の調整の問題も回避し、依存関係を軽減し、John Ousterhout によって提案されたソフトウェア設計原則に準拠します。
前処理プロセスと後処理プロセスを GPU のニーズに合わせて移動する複数の要件条件を満たすため。
#1 つ目は、CPU のパフォーマンスが少なくとも CPU よりも優れている必要があるということです。これは主に、GPU の高い同時コンピューティング能力に基づいています。
#2 つ目は、前処理を高速化し、モデル推論などの他のプロセスに悪影響を与えないようにすることです。 2 番目の要件については、CV-CUDA の各オペレーターにはストリームと CUDA メモリ間のインターフェイスがあり、GPU リソースをより合理的に割り当てることができるため、これらの前処理オペレーターを GPU 上で実行するときに大きな影響を与えることはありません。モデル計算自体に。
第三に、インターネット企業は非常に多様なビジネス ニーズを持っており、多くの種類のモデルとそれに対応する前処理ロジックが関係するため、前処理計算のサブクラスを開発する必要があります。カスタマイズできるため、複雑なロジックをより柔軟に実装できるようになります。
# 一般的に、CV-CUDA はハードウェア、ソフトウェア、アルゴリズム、前処理と後処理の段階が高速化され、パイプライン全体が統合されます。
#ソフトウェアに関しては、CV-CUDA はさらなる最適化のために多数のソフトウェア最適化手法を開発しました。これには、パフォーマンスの最適化 (メモリ アクセスの最適化など) やリソース使用率の最適化 (ビデオ メモリの事前割り当てなど) が含まれるため、クラウド トレーニングや推論のシナリオで効率的に実行できます。
#1 つ目は、ビデオ メモリの事前割り当て設定です。 OpenCV が GPU バージョンを呼び出すと、一部のオペレーターが内部で cudaMalloc を実行するため、消費時間が大幅に増加します。 CV-CUDA では、すべてのビデオ メモリの事前割り当てが初期化フェーズで実行され、トレーニング フェーズと推論フェーズではビデオ メモリの割り当て操作が実行されないため、効率が向上します。
#第 2 に、すべての演算子は非同期で動作します。 CV-CUDA は多数のカーネルを統合することでカーネルの数を減らし、カーネルの起動時間とデータのコピーと消去を短縮し、全体的な動作効率を向上させます。
第三に、CV-CUDA は、メモリ アクセスのマージ、ベクトル化された読み取りと書き込みなどのメモリ アクセスも最適化して、帯域幅の使用率を向上させ、共有メモリの使用も行います。メモリアクセス、読み取りおよび書き込み効率を向上させるためのメモリ。
最後に、CV-CUDA では、高速計算、ワープ リデュース/ブロック リデュースなど、計算において多くの最適化も行われています。
アルゴリズムに関しては、CV-CUDA のオペレーターは、非常に複雑なロジック実装をサポートするために独立して設計およびカスタマイズされており、簡単に実装できます。使用してデバッグします。
独立したデザインを理解するにはどうすればよいですか?画像処理ライブラリにおけるオペレータ呼び出しには、DALIなどのパイプラインの結果のみを取得できる全体パイプライン形式と、オペレータごとに取得できるモジュール独立オペレータ形式の2種類があります。 OpenCV などの個別の結果。 CV-CUDA は OpenCV と同じ呼び出し形式を使用するため、使用とデバッグがより便利です。
#言語に関しては、CV-CUDA は事前と事後をシームレスに接続できる豊富な API をサポートしています。 - トレーニングおよび推論シナリオへの処理。
これらの API には、一般的に使用される C、C、Python インターフェイスなどが含まれており、トレーニングと推論の両方のシナリオをサポートできます。また、PyTorch と TensorRT もサポートしています。 . インターフェイス、将来的には、CV-CUDA は Triton、TensorFlow、JAX などのインターフェイスもサポートする予定です。
推論段階では、前処理と後処理のモデルが確実に実行される限り、推論に Python または C インターフェイスを直接使用できます。 、および GPU は、推論中に同じストリーム上に配置されます。
NVIDIA での CV-CUDA の使用をデモンストレーションすることによって、NVIDIA、Jiedong と Sina Weibo のアプリケーション事例から、CV-CUDA によってもたらされるパフォーマンスの向上がいかに重要であるかを理解できます。
#最初は、NVIDIA が示した画像分類の事例です。
#画像分類パイプラインでは、最初は画像をデコードする JPEG デコードです。緑色の部分は、サイズ変更やデータの変換などの前処理ステップです。型付け、正規化、再フォーマット。青い部分は PyTorch を使用した前向き推論プロセスで、最後に分類結果がスコア付けされて並べ替えられます。
CV-CUDA と OpenCV の CPU バージョンと GPU バージョンのパフォーマンスを比較すると、 GPU 版の OpenCV は CPU 版と比較して大きなパフォーマンス向上を実現でき、CV-CUDA を適用することでパフォーマンスを 2 倍にすることができます。たとえば、OpenCV の CPU オペレータによって 1 ミリ秒あたりに処理される画像の数は 22 で、GPU オペレータによって 1 ミリ秒あたりに処理される画像の数は 200 を超えます。CV-CUDA は 1 ミリ秒あたり 500 を超える画像を処理でき、そのスループットはOpenCV の CPU と比べて 20 倍以上、GPU 版と比べて 2 倍以上となっており、性能の向上は明らかです。
#2 つ目は、ByteDance が提示した OCR1、OCR2、およびビデオ マルチモダリティの 3 つのケースです。
#モデル トレーニングでは、OCR1、OCR2、ビデオ マルチモーダルでそれを確認できます。 CV-CUDA を使用した後、3 つのタスクで 50% から 100% のパフォーマンス向上が得られました。 パフォーマンスがこれほど大幅に向上するのはなぜですか?実際、これら 3 つのタスクに共通することの 1 つは、デコード、サイズ変更、トリミングなどの画像前処理ロジックが非常に複雑であり、これらは依然として大きなカテゴリであるということです。演算子のカテゴリ。クラスまたはサブクラスの前処理。これら 3 つのタスクでは、前処理リンクで十数種類のデータ拡張が行われる可能性があるため、CPU の計算負荷が非常に高くなります。計算のこの部分を GPU に移動できれば、CPU のリソース競合が発生します。大幅に削減され、全体のスループットが大幅に向上します。 #最後に、新浪微博で紹介されたビデオ処理の事例があります。
#ビデオ処理プロセスの場合、従来のアプローチでは、最初にビデオ フレームを配置します。 CPU 環境 デコード: 元のバイト ストリームを画像データにデコードし、サイズ変更、トリミングなどの通常の操作を実行して、特定のモデルの計算のためにデータを GPU にアップロードします。
#CV-CUDA の処理方法は、CPU をデコードして、バイト ストリームは GPU にアップロードされ、前処理も GPU 上に配置されるため、ビデオ メモリとメモリ間のコピー操作を必要とせずにモデル計算にシームレスに接続できます。
図は、OpenCV (奇数) と CV-CUDA (偶数) の使用を示しています。それぞれの処理時間。青はモデルの消費時間、オレンジはデコードの消費時間、緑は前処理の消費時間を示します。
#OpenCV は CPU デコードと GPU デコードの 2 つのモードに分けることができますが、CV-CUDA は GPU デコード モードのみを使用します。#CPU でデコードされた OpenCV の場合、OpenCV のデコードと前処理は CV-CUDA よりもはるかに時間がかかることがわかります。
GPU デコードを使用した OpenCV のケースを見ると、OpenCV と CV が- モデルとデコード部分の CUDA の時間は近づいていますが、前処理にはまだ大きな差があります。
パイプライン全体の比較という点では、CV-CUDA にも明らかな利点があります。つまり、GPU 使用率がフルの場合、CV-CUDA は OpenCV の CPU 構成の 10% のみを必要とし、同時に CV-CUDA はより多くの GPU リソースを節約します。パイプライン、CV-CUDA 効率が 70% 向上しました。
6.
今後の展望まず第一に、CV-CUDA は実際には万能薬ではありません。たとえば、モデルのトレーニング段階で、ボトルネックが前処理ではなく、データの読み取りとモデルの推論にある場合です。現時点では、CV-CUDA を使用して元の前処理ソリューションを置き換えても、実際には役に立ちません。
さらに、CV-CUDA を使用するプロセスにおいて、CPU と GPU のワークロードが前処理ロジックに適切に割り当てられている場合、より優れたパフォーマンス結果が達成される場合があります。
たとえば、CPU は画像をデコードしてサイズ変更し、サイズ変更後の処理のために GPU に画像を置くことができます。
なぜデコードとサイズ変更を CPU 上で行うのでしょうか?まず、画像デコードの場合、GPU のハード デコード ユニットには実際には制限があります。次に、サイズ変更については、通常、サイズ変更を行うと、より大きな画像がより小さな画像に変換されます。
サイズ変更前にデータが GPU にコピーされると、ビデオ メモリのデータ転送に多くの帯域幅を占有する可能性があります。
もちろん、CPU と GPU の間でワークロードをどのように割り当てるかについては、実際の状況に基づいて判断する必要があります。
最も重要な原則は、デバイス間でデータを送信する際にオーバーヘッドが発生するため、CP U と GPU の間で計算を交互に行わないことです。変更が頻繁すぎると、計算自体によってもたらされる利点が平坦になり、パフォーマンスが向上するのではなく低下する可能性があります。
2022 年 12 月、CV-CUDA はアルファ版をリリースしました。これには、一般的に使用される反転、回転、透視図法、サイズ変更などの 20 以上の演算子が含まれています。 . .
現在、OpenCV にはさらに多くの演算子があり、数千の演算子が含まれています。CV-CUDA は現在、より一般的に使用される演算子のみを高速化しますが、将来的にも高速化し続ける予定です。 . 新しい演算子を追加します。
CV-CUDA は今年 3 月にベータ版もリリースされ、20 人以上のオペレーターが追加され、50 人以上のオペレーターが追加されます。ベータ版には、ConvexHull、FindContours など、非常に一般的に使用される演算子がいくつか含まれています。
戻る探していますCV-CUDAの設計計画に戻ってみると、その背後にそれほど複雑な原理はなく、一見して明快であることがわかります。
#複雑さの観点から見ると、これは CV-CUDA の利点であると言えます。 「ソフトウェア設計の哲学」では、ソフトウェアの複雑さを判断するための原則について言及しています。つまり、ソフトウェア システムが理解して変更するのが難しい場合、それは非常に複雑であり、理解して変更するのが簡単な場合、それは非常に単純です。
CV-CUDA の有効性は、モデル計算段階の GPU への適応性として理解でき、これが前後の適応性を促進します。処理ステージを GPU に転送します。そして、この傾向は実際に始まったばかりです。
以上がスループットが 30 倍に向上: CV パイプラインがフルスタック並列化に移行の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。