Open yukarinoki opened 1 year ago
APIコールをラッパーライブラリでインターセプトし、関数パラメータから利用率を測定。
GPUコアのアプリケーション使用の監視。CUDAアプリケーションでは、GPUコアの占有率と各カーネル関数の実行時間を評価することで、アプリケーションのGPUコアの需要を取得することができます。これは、タイマー関数を使用して取得できます。カーネルのGPUコア占有率は、cuOccupancyMaxActiveBlocksPerMultiprocessor()とカーネル関数のいくつかのパラメータ(カーネル関数のポインタ、ブロック数、ブロックあたりのスレッド数など)を使用して推定することができます。
ただし、カーネル関数が呼び出されるたびにGPUコアの占有率を評価すると、アプリケーションのパフォーマンスが大幅に低下する可能性があります。この問題を解決するために、DCUDAは、カーネル関数が初めて呼び出されたときにそれを評価し、その情報を記録し、カーネルが同じシステムパラメータ(例えば、スレッド数)で再度呼び出されたときにこれらの記録された情報を使用します。その理由は、GPUアプリケーションは通常、イテレーションベースの計算であるため、同じカーネル関数を何度も呼び出す可能性があるからです。
GPUメモリのアプリケーション使用の監視。CUDAアプリケーションは、通常、cuMemAlloc()のようなAPIを使用して必要なGPUメモリのほとんどを割り当てます。したがって、割り当てられたメモリサイズと仮想アドレスの範囲を割り当てAPIのパラメータから取得します。しかし、割り当てられたGPUメモリのすべてがアプリケーションによって使用されるわけではなく、統一メモリは仮想アドレスを物理GPUメモリにマッピングしますが、それはアプリケーションによってアクセスされているときにのみ行います。例えば、tensor$ow [7]やtheano [8]などのCUDAライブラリに基づいて実装された一部の機械学習プラットフォームでは、アプリケーションは通常、全てのGPUメモリを割り当てますが、そのうちの非常に小さい部分しか使用しないかもしれません。未使用のデータをプリフェッチすることを避けるために、GPUメモリの実際の使用を検出する必要があります。
GPUメモリの実際の使用を検出するために、私たちはメモリポインタが本当にGPUメモリを指しているかどうかをcuPointerGetA!ribute()を使用して確認する監視方法を提案します。しかし、すべてのポインタを確認すると大きなオーバーヘッドが生じます。私たちはサンプリング方法を使用してモニタオーバーヘッドを減らします。具体的には、私たちは固定のステップサイズ(つまり、64MB)でメモリ使用情報をサンプリングします。64MBの領域ごとに、私たちは1ページだけを確認します。このページが使用されている場合、私たちは全体の64MBのデータをプリフェッチを介して移行します。ここで、サンプリング方法を使用すると、偽陰性、つまり、実際に使用されているページが識別されず、プリフェッチ操作を使用して移行できない可能性があることに注意してください。しかし、この偽陰性はアプリケーションの実行の正確さに影響を与えません。なぜなら、これらの省略されたページは、ページフォールトが発生したときにオンデマンドページングを経由して宛先のGPUに移行することができるからです(セクション3.4を参照)。
カーネル呼び出しの間でマイグレーションする。GPUでは、カーネル呼び出し中の実行状態を保存する方法がない。
。CUDAと既存の研究では、汎用的なライブマイグレーション機能を提供しておらず、ライブマイグレーション設備の設計と実装においては3つの課題があります。
一貫したランタイム環境のクローニング。アプリケーションのランタイム環境には、カーネルのバイナリ、ストリーム、そしてcublasハンドル、cudnnハンドル、cu!tハンドルなどの関連ライブラリのハンドルが含まれていることがわかります。これらの変数は、GPUの制御と利用のための全ての管理データを保持しています。したがって、一貫したランタイム環境をクローンするためには、まずターゲットGPU上で必要な全てのライブラリを初期化し、これらのライブラリの新しいハンドルを作成し、次にソースGPU上の対応する変数から設定情報をコピーします。さらに、カーネル関数のバイナリを登録する必要があります。これにより、ターゲットGPU上のアプリケーションから呼び出すことができるようになります。
また、ランタイムのクローニングには大きなオーバーヘッドが生じることを発見しました。その主な原因はライブラリの初期化であり、特に、アプリケーションの必要なライブラリの初期化に必要な時間は200ms - 400msとなり、全体のクローニング時間の80%以上を占めることがあります。このオーバーヘッドを削減するために、我々はハンドルプール技術を採用し、各GPUでライブラリのハンドルのプールを維持します。これにより、ライブラリを初期化し、バックグラウンドでハンドルを作成します。クローニング時には、DCUDAは新たにハンドルを作成する代わりに、ハンドルプールから必要なライブラリのハンドルを即座に取得することができます。
カーネル関数のバイナリを登録することによるオーバーヘッドを削減するためには、多くのバイナリが、ターゲットGPUに移行された後のアプリケーションの残りのタスクには必要とされない可能性があることを考慮すると、DCUDAはカーネル関数のバイナリをオンデマンドで登録するポリシーを採用しています。具体的には、DCUDAはアプリケーションが必要とするカーネル関数のバイナリのコピーをCPUメモリに保持し、各バイナリと対応するカーネル関数との関係を記録します。DCUDAは、カーネル関数が実際に呼び出されたときに、カーネルバイナリの登録をオンデマンドでトリガーします。
https://www.cse.cuhk.edu.hk/~cslui/PUBLICATION/SOCC_2019_B.pdf
クラウドとデータセンターでは、複数のGPUを搭載したGPUサーバーが広く展開されています。現在の最先端のGPUスケジューリングアルゴリズムは、アプリケーションを異なるGPUに「静的に」割り当てるものです。これらのアルゴリズムは通常、GPUの利用率の動向を無視し、アプリケーションを割り当て/実行する前にリソース需要を見積もる際にしばしば不正確であるため、ロードバランスをさらに改善し、GPU利用率を向上させる大きな機会があります。CUDA(Compute Unified Device Architecture)をベースに、我々は複数のGPU間で実行中のアプリケーションを「動的」にスケジューリングするためのランタイムシステムであるDCUDAを開発しました。特に、DCUDAはアプリケーションのリソース需要とGPU利用率を正確にモニタリングするためのリアルタイムで軽量な方法を提供します。さらに、実行中のアプリケーションをGPU間で移行するための普遍的な移行機能を提供し、そのオーバーヘッドはほとんど無視できます。さらに重要なことに、DCUDAはすべてのCUDAアプリケーションをそのソースコードを変更することなく透明にサポートします。我々のプロトタイプシステムでの実験結果は、DCUDAがGPUの過負荷時間を平均で78.3%削減できることを示しています。その結果、我々が調査した幅広いアプリケーションで構成される異なるワークロードに対して、DCUDAはアプリケーションの平均実行時間を最大42.1%削減することができます。さらに、DCUDAは軽負荷シナリオでのエネルギーを13.3%削減します。