午前9時PSTでMLシンポジウム、この10月19日(火曜日)の最初の女性の中にチューン今すぐ登録

プロファイラを使用した TensorFlow のパフォーマンス最適化

プロファイラが提供しているツールを使用し、TensorFlow モデルのパフォーマンスを追跡します。また、ホスト(CPU)、デバイス(GPU)、またはホストとデバイスの両方の組み合わせでモデルがどのように機能するかを確認します。

プロファイリングは、モデル内のさまざまな TensorFlow 演算(op)によるハードウェアリソース消費(時間とメモリ)を把握し、パフォーマンスのボトルネックを解消して最終的にモデルの実行を高速化するのに役立ちます。

このガイドでは、プロファイラのインストール方法、利用可能なさまざまなツール、プロファイラのさまざまなパフォーマンスデータ収集モード、およびモデルのパフォーマンスを最適化するために推奨されるベストプラクティスについて説明します。

Cloud TPU 上でモデルのパフォーマンスをプロファイリングする場合は、 Cloud TPU のガイドをご覧ください。

プロファイラのインストールと GPU の要件

GitHub リポジトリから install_and_run.py スクリプトをダウンロードして実行し、プロファイラをインストールしてください。

GPU 上でプロファイリングを実行するには、次の手順を行う必要があります。

  1. TensorFlow GPU サポートソフトウェアの要件に記載されている NVIDIA® GPU ドライバーと CUDA® Toolkit の要件を満たします。

  2. CUPTI がパスに存在することを確認します。

    /sbin/ldconfig -N -v $(sed 's/:/ /g' <<< $LD_LIBRARY_PATH) | \
    grep libcupti
    

パスに CUPTI が存在しない場合は、次のコマンドを実行してインストールディレクトリを $LD_LIBRARY_PATH 環境変数の前に追加します。

export LD_LIBRARY_PATH=/usr/local/cuda/extras/CUPTI/lib64:$LD_LIBRARY_PATH

上記の ldconfig コマンドを再度実行し、CUPTI ライブラリが検出されたことを確認してください。

特権の問題を解消する

Docker 環境または Linux で CUDA® Toolkit を使用してプロファイリングを実行する場合、CUPTI 権限の不足に関する問題(CUPTI_ERROR_INSUFFICIENT_PRIVILEGES)が発生する場合があります。Linux でこの問題を解消する方法については、NVIDIA 開発者ドキュメント をご覧ください。

Docker 環境で CUPTI 特権の問題を解消するには、以下を実行してください。

docker run option '--privileged=true'

プロファイラツール

プロファイラには、一部のモデルデータをキャプチャした後にのみ表示される TensorBoard の Profile タブからアクセスできます。

注意: プロファイラは Google Chart ライブラリを読み込むため、インターネットアクセスを要求します。TensorBoard をローカルマシン上、企業内ファイアウォールの背後、またはデータセンターで完全にオフラインで実行する場合、一部のチャートやテーブルが表示されない場合があります。

プロファイラには、次のようなパフォーマンス分析に役立つツールが含まれています。

  • 概要ページ
  • 入力パイプライン分析ツール
  • TensorFlow 統計
  • トレースビューア
  • GPU カーネル統計
  • メモリプロファイルツール
  • Pod ビューア

概要ページ

概要ページでは、プロファイリングを実行中にモデルがどのように動作したかが一番上に表示されます。このページには、ホストとすべてのデバイスの概要を集約したページと、モデルのトレーニングパフォーマンスを改善するためのいくつかの推奨事項が表示されます。Host ドロップダウンで個々のホストを選択することもできます。

概要ページには、次のようにデータが表示されます。

image

  • Performance Summary - モデルのパフォーマンスの概要が表示されます。パフォーマンスの概要は、次の2つの部分に分かれています。

    1. ステップ時間の内訳 - 平均ステップ時間を、時間を消費した場所に応じて複数のカテゴリに分類しています。

      • Compilation - カーネルのコンパイルに費やされた時間
      • Input - 入力データの読み込みに費やされた時間
      • Output - 出力データの読み込みに費やされた時間
      • Kernel Launch - ホストがカーネルを起動するのに費やされた時間
      • Host Compute Time - ホストの演算時間
      • Device to Device Time - デバイス間の通信時間
      • Device Compute Time - デバイス上の演算時間
      • Python のオーバーヘッドを含むその他すべての時間
    2. Device Compute Precisions - 16 ビットおよび 32 ビット計算を使用するデバイス演算時間の割合を報告します。

  • Step-time Graph - サンプリングされたすべてのステップのデバイスステップ時間(ミリ秒単位)のグラフを表示します。各ステップは、時間を費やしている箇所によって複数のカテゴリに(別々の色で)分かれています。赤い領域は、デバイスがホストからの入力データを待機してアイドル状態であったステップ時間の部分に対応しています。緑の領域は、デバイスが実際に動作していた時間の長さを示しています。

  • デバイスでの上位 10 個の TensorFlow 演算 - 最も多くの時間が費やされたデバイス上の演算が表示されます。

    各行には、演算に費やされた自己時間(すべての演算にかかった時間に占める割合)、累積時間、カテゴリ、名前が表示されます。

  • 実行環境 - 以下を含むモデルの実行環境の高度な概要が表示されます。

    • 使用されたホストの数
    • デバイスのタイプ(GPU/TPU)
    • デバイス コアの数
  • 次の推奨ステップ - モデルで入力処理の負荷が高くなった場合に報告され、モデルのパフォーマンス ボトルネックを特定して解消するのに使用できるツールが提案されます。

入力パイプライン分析ツール

TensorFlow プログラムがファイルからデータを読み込むと、TensorFlow グラフにパイプライン方式でデータが表示されます。読み取りプロセスは連続した複数のデータ処理ステージに分割され、1 つのステージの出力が次のステージの入力となります。この読み込み方式を入力パイプラインといいます。

ファイルからレコードを読み取るための一般的なパイプラインには、次のステージがあります。

  1. ファイルの読み取り
  2. ファイルの前処理(オプション)
  3. ホストからデバイスへのファイル転送

入力パイプラインが非効率な場合、アプリケーションの速度が大幅に低下する可能性があります。入力パイプラインに多くの時間が費やされている場合、このアプリケーションは入力処理の負荷が高いとみなされます。入力パイプライン分析ツールを使用すると、非効率な入力パイプラインを特定できます。

入力パイプライン分析ツールは、プログラムで入力処理の負荷が高くなっているかどうかを即座に通知し、入力パイプラインの任意のステージでパフォーマンスボトルネックをデバッグするために、デバイス側とホスト側の分析を案内します。

データ入力パイプラインを最適化するための推奨ベストプラクティスについては、入力パイプラインのパフォーマンスに関するガイダンスをご覧ください。

入力パイプライン ダッシュボード

入力パイプライン分析ツールを開くには、Profile を選択し、Tools プルダウンから input_pipeline_analyzer を選択します。

image

ダッシュボードには次の 3 つのセクションがあります。

  1. サマリー - 入力パイプライン全体のサマリーが表示されます。たとえば、アプリケーションで入力処理の負荷が高いかどうか表示されます。入力バウンドの場合はその量も表示されます。
  2. デバイス側の分析 - デバイス側の分析結果が表示されます。デバイスのステップ時間、各ステップのコアで入力データの待機に費やしたデバイス時間などが表示されます。
  3. ホスト側の分析 - ホスト側の分析結果が表示されます。ホスト上での入力処理時間の内訳などが表示されます。

入力パイプラインのサマリー

サマリーは、ホストからの入力待ちに費やされたデバイス時間の割合が表示されます。これにより、プログラムで入力処理の負荷が高くなっているかどうかを確認できます。インストゥルメント化された標準の入力パイプラインを使用している場合は、ツールによって多くの入力処理時間が費やされている部分が報告されます。

デバイス側の分析

デバイス側の分析では、デバイスとホストの間で費やされた時間と、ホストからの入力データの待機に費やされたデバイス時間が表示されます。

  1. ステップ番号に対してプロットされたステップ時間 - サンプリングされたすべてのステップのデバイス ステップ時間(ミリ秒単位)がグラフに表示されます。各ステップは、時間が費やされた箇所によって複数のカテゴリに(別々の色で)分かれています。赤色の領域は、デバイスがホストからの入力データを待機しているステップ時間に対応します。緑色の領域は、デバイスが実際に稼働していた時間の長さを表します。
  2. ステップ時間の統計 - デバイス ステップ時間の平均、標準偏差、範囲([最小、最大])が報告されます。

ホスト側の分析

ホスト側の分析には、ホスト上での入力処理時間(tf.data API 演算に費やされた時間)の内訳が次のいくつかのカテゴリに分類されて表示されます。

  • ファイルからのオンデマンドのデータ読み取り - キャッシュ、プリフェッチ、インターリーブなしで、ファイルからデータを読み取る際に費やされた時間。
  • ファイルからの事前のデータ読み取り - キャッシング、プリフェッチ、インターリーブを含め、ファイルの読み取りに費やされた時間。
  • データの前処理 - 画像の圧縮など、前処理の演算に費やされた時間。
  • デバイスに転送するデータのエンキュー - デバイスへの転送前にデータがインフィード キューに追加される際に費やされた時間。

個々の入力演算の統計とそのカテゴリの内訳を実行時間別に表示するには、Input Op Statistics を展開します。

image

ソース データ テーブルには、次の情報を含む各エントリが表示されます。

  1. 入力演算 - 入力演算の TensorFlow 演算名が表示されます。
  2. 件数 - プロファイリング期間中に実行された演算のインスタンスの合計数が表示されます。
  3. 合計時間(ミリ秒) - 各インスタンスに費やされた時間の累積合計が表示されます。
  4. 合計時間(%) - 演算に費やされた合計時間が、入力処理に費やされた合計時間との割合で表示されます。
  5. 合計自己時間(ミリ秒) - 各インスタンスに費やされた自己時間の累積合計が表示されます。この自己時間は、関数の本文内で費やされた時間を測定したもので、関数の本文から呼び出される関数で費やされた時間は含まれません。
  6. 合計自己時間(%) - 合計自己時間が、入力処理に費やされた合計時間との割合で表示されます。
  7. カテゴリ - 入力演算の処理カテゴリが表示されます。

TensorFlow 統計

TensorFlow Stats ツールには、プロファイリングセッション中にホストまたはデバイスで実行されるすべての TensorFlow演算(op)のパフォーマンスが表示されます。

image

このツールでは 2 つのペインでパフォーマンス情報が表示されます。

  • 上のペインには、最大 4 つの円グラフが表示されます。

    1. ホスト上の各演算の自己実行時間の分布
    2. ホスト上の各演算タイプの自己実行時間の分布
    3. デバイス上の各演算の自己実行時間の分布
    4. デバイス上の各演算タイプの自己実行時間の分布
  • 下のペインには、TensorFlow 演算に関するデータを報告するテーブルが表示されており、各演算に 1 行、各タイプのデータに 1 列(列の見出しをクリックして列をソート)が割り当てられています。上のペインの右側にある Export as CSV ボタンをクリックすると、このテーブルのデータが CSV ファイルとしてエクスポートされます。

    注意点:

    • 子の演算を持つ演算がある場合:

      • 演算の「累積」時間の合計には、子の演算内で費やされた時間が含まれています。
      • 演算の合計「自己」時間の合計には、子の演算内で費やされた時間が含まれていません。
    • 演算がホスト上で実行される場合:

      • 演算によって発生するデバイスの合計自己時間のパーセンテージは 0 になります。
      • この演算までを含むデバイスの合計自己時間の累積パーセンテージは 0 になります。
    • 演算がデバイス上で実行される場合:

      • この演算で発生するホストの合計自己時間の割合は 0 になります。
      • この演算までを含むホストの合計自己時間の累積的な割合は 0 になります。

円グラフとテーブルにアイドル時間を含めるか除外するかを選択できます。

トレースビューア

トレースビューアには次のタイムラインが表示されます。

  • TensorFlow モデルによって実行された演算の実行期間。
  • 演算を実行したシステムの部分(ホストまたはデバイス)。通常、ホストが入力演算を実行し、トレーニングデータを前処理してデバイスに転送し、デバイスは実際のモデルトレーニングを行います。

トレースビューアを使用して、モデル内のパフォーマンスの問題を特定し、この問題を解決する対策を講じることができます。たとえば、入力とモデルトレーニングのどちらに大部分の時間を費やしているかどうかを大まかに識別できます。さらに詳しく見ると、どの演算の実行に最も時間がかかっているかも識別できます。トレースビューアで表示できるのはデバイスごとに 100 万イベントまでです。

トレースビューアのインターフェース

トレースビューアを開くと、最新の実行結果が表示されます。

image

この画面には、次の主要な要素が表示されます。

  1. Timeline ペイン - デバイスとホストで実行された演算が時系列で表示されます。
  2. Details ペイン -Timeline ペインで選択した演算の詳細情報が表示されます。

Timeline ペインには、次の要素が含まれます。

  1. 上部バー - さまざまな補助コントロールが含まれています。
  2. 時間軸 - トレースの開始時点を基準とした時間が表示されます。
  3. セクションとトラックラベル - 各セクションには複数のトラックが含まれています。左側にある三角形をクリックすると、セクションの展開や折りたたみを行うことができます。システムで処理中の要素ごとに 1 つのセクションがあります。
  4. ツールセレクタ -Zoom、Pan、Select、Timing などのトレースビューアを操作するさまざまなツールが用意されています。
  5. イベント - これらのイベントは、演算が実行されていた時間やトレーニングステップなどのメタイベントの期間を示します。
セクションとトラック

トレースビューアには、次のセクションがあります。

  • デバイスノードごとに 1 つのセクション。ラベルとしてデバイスチップの数とチップ内のデバイスノードの数が使用されます(例: 「/device:GPU:0 (pid 0)」)。デバイスノードのセクションには、次のトラックが含まれます。
    • Step - デバイスで実行されていたレーニングステップの期間が表示されます。
    • TensorFlow Ops - デバイス上で実行された演算が表示されます。
    • XLA Ops - XLA が使用されているコンパイラである場合にデバイス上で実行された XLA 演算が表示されます。1 つの TensorFlow 演算が 1 つ以上の XLA 演算に変換されます。XLA コンパイラにより、XLA 演算がデバイス上で実行されるコードに変換されます。
  • ホストマシンの CPU 上で実行されるスレッドのセクション - 「Host Threads」というラベルが付いています。このセクションには、CPU スレッドごとに 1 つのトラックが含まれます。セクションラベルと一緒に表示される情報は無視してもかまいません。
イベント

タイムライン内のイベントは異なる色で表示されます。色自体には特別な意味はありません。

トレースビューアは TensorFlow プログラム内の Python 関数呼び出しのトレースも表示できます。tf.profiler.experimental.start() API を使用する場合は、プロファイリングを開始する際に ProfilerOptions 名前付きタプルを使用して Python のトレースを有効化できます。または、プロファイリングにサンプリングモードを使用する場合は、[Capture Profile] ダイアログのドロップダウンオプションを使用してトレースのレベルを選択することができます。

image

GPU カーネル統計

このツールには、すべての GPU アクセラレータカーネルのパフォーマンス統計と元の演算を表示されます。

image

このツールでは 2 つのペインで情報が表示されます。

  • 上部のペインには、合計経過時間が最も長い CUDA カーネルを示す円グラフが表示されます。

  • 下のペインには、一意のカーネルと演算のペアごとに次のデータを含むテーブルが表示されます。

    • カーネルと演算のペアでグループ化された合計経過 GPU 時間の順位(降順)。
    • 起動されたカーネルの名前
    • カーネルが使用している GPU レジスタの数
    • 使用されている共有(静的+動的共有)メモリの合計サイズ(バイト単位)
    • blockDim.x, blockDim.y, blockDim.z で表現されたブロックの次元
    • gridDim.x, gridDim.y, gridDim.z で表現されたグリッドの次元
    • 演算が TensorCore を使用可能かどうか
    • カーネルに TensorCore 命令が含まれているかどうか
    • このカーネルを起動した演算の名前
    • このカーネルと演算のペアが発生した数
    • 合計経過 GPU 時間(マイクロ秒)
    • 平均経過 GPU 時間(マイクロ秒)
    • 最短経過 GPU 時間(マイクロ秒)
    • 最長経過 GPU 時間(マイクロ秒)

メモリのプロファイリングツール

メモリプロファイルツールは、プロファイリング間のデバイスのメモリ使用状況を監視します。このツールを使用して、次のことを実行できます。

  • ピークメモリ使用状況とそれに対応する TensorFlow 演算への割り当てメモリを特定することで、メモリ不足(OOM)の問題をデバッグします。また、マルチテナントの推論を実行する場合に発生する OOM 問題もデバッグできます。
  • メモリの断片化の問題をデバッグします。

メモリプロファイルツールには、次の 3 つのセクションにデータが表示されます。

  1. メモリプロファイルのサマリー
  2. メモリのタイムライングラフ
  3. メモリの詳細テーブル

メモリプロファイルのサマリー

このセクションには、以下に示されるように、TensorFlow プログラムの要約が表示されます。

<img src="./images/tf_profiler/memory_profile_summary.png" width="400", height="450">

メモリプロファイルのサマリーには、次の 6 つのフィールドがあります。

  1. Memory ID - すべての利用可能なデバイスメモリシステムをリストするドロップダウン。ドロップダウンから、表示するメモリシステムを選択できます。
  2. #Allocation - プロファイリングのインターバル中に作成されるメモリ割り当ての数です。
  3. #Deallocation - プロファイリングのインターバル中に行われるメモリ割り当て解除の数です。
  4. Memory Capacity - 選択したメモリシステムの合計容量(GB)です。
  5. Peak Heap Usage - モデルが実行し始めてからのピークメモリ使用率(GiB)です。
  6. Peak Memory Usage - プロファイリングのインターバル中のピークメモリ使用率(GiB)です。このフィールドには次のサブフィールドがあります。
    1. Timestamp - タイムライングラフ上でピークメモリ使用率が発生したときのタイムスタンプです。
    2. Stack Reservation - スタックに予約されたメモリの量(GiB)です。
    3. Heap Allocation - ヒープに割り当てられたメモリの量(GiB)です。
    4. Free Memory - 空きメモリの量(GiB)です。Memory Capacity は、Stack Reservation、Heap Allocation、および Free Memory の総計です。
    5. Fragmentation - 断片率です(低いほど良)。(1 - 空きメモリの最大チャンクサイズ / 合計空きメモリ)のパーセント率で計算されます。

メモリのタイムライングラフ

このセクションには、メモリ使用率(GiB)と断片率を時間(ms)比較した図が表示されます。

image

X 軸は、プロファイリングインターバルのタイムライン(ms)を表します。左の Y 軸はメモリ使用率(GiB)を、右の Y 軸は断片率を表します。合計メモリは、X 軸のある時点で、スタック(赤)、ヒープ(オレンジ)、空き(緑)の 3 つに分けて示されています。特定のタイムスタンプにマウスポインタを合わせると、以下のように、その時点でのメモリの割り当てと割り当て解除の詳細を確認できます。

image

ポップアップウィンドウには、次の情報が表示されます。

  • timestamp(ms) - タイムライン上の選択されたイベントの場所
  • event - イベントの種類(割り当てまたは割り当て解除)
  • requested_size(GiB)- 要求されたメモリ量。割り当て解除イベントの場合、これは負の値になります。
  • allocation_size(GiBs) - 割り当てられた実際のメモリ量。割り当て解除イベントの場合、これは負の値になります。
  • tf_op - 割り当てと割り当て解除を要求する TensorFlow Op
  • step_id - このイベントが発生したトレーニングステップ
  • region_type - この割り当てメモリの対象であるデータエントリーの種類。可能な値は、一時を意味する temp、アクティベーションと勾配の output、および重みと定数の persist/dynamic です。
  • data_type - テンソル要素の種類(8-bit 署名無し整数を表す uint8 など)
  • tensor_shape - 割り当て/割り当て解除されるテンソルの形状
  • memory_in_use(GiBs) - この時点で使用されている合計メモリ

メモリの詳細テーブル

このテーブルには、プロファイリングインターバルのピークメモリ使用率の時点でアクティブなメモリの割り当てが示されます。

image

TensorFlow 演算ごとに 1 つの行があり、各行には次の列があります。

  • Op Name - TensorFlow 演算の名前
  • Allocation Size (GiBs) - この演算に割り当てられている合計メモリ量
  • Requested Size (GiBs) - この演算に要求されたメモリの合計量
  • Occurrences - この演算の割り当て数
  • Region type - この割り当てメモリの対象であるデータエンティティの種類。可能な値は、一時を意味する temp、活性化と勾配の output、および重みと定数の persist/dynamic です。
  • Data type - テンソル要素の型
  • Shape - 割り当てられたテンソルの形状

注意: テーブル内のすべての列は並べ替え可能で、演算名で行をフィルタできます。

Pod ビューア

Pod ビューアツールには、すべてのワーカーのトレーニングステップの詳細が表示されます。

image

  • 上部のペインには、ステップ番号を選択するためのスライダーがあります。
  • 下部のペインには、スタックされた列のグラフが表示されます。これは相互に重なったステップ時間カテゴリの詳細を示す要約です。各スタックの列は、一意のワーカーを表します。
  • スタックされた列にマウスポインタを合わせると、左側のカードにそのステップの詳細に関するさらに詳しい情報が表示されます。

tf.data のボトルネック分析

警告: このツールは実験的です。分析結果が誤っていると思われる場合は、こちらに報告してください。

tf.data ボトルネック分析は、プログラム内の tf.data 入力パイプラインに存在するボトルネックを自動的に検出し、その修正方法を推奨します。プラットフォーム(CPU/GPU/TPU)やフレームワーク(TensorFlow/JAX)に関係なく、tf.data を使用しているあらゆるプログラムで機能します。分析と推奨は、こちらのガイドに基づきます。

次のステップで、ボトルネックを検出します。

  1. 最も多い入力バウンドのホストを見つけます。
  2. 最も実行の遅い tf.data 入力パイプラインを見つけます。
  3. プロファイラのトレースから入力パイプラインのグラフを再構築します。
  4. 入力パイプライングラフの重要なパスを見つけます。
  5. その重要なパスで最も遅い変換をボトルネックとして識別します。

UI は、パフォーマンス分析サマリー、全入力パイプラインのサマリー、入力パイプラインのグラフの 3 つのセクションに分かれています。

パフォーマンス分析サマリー

image

このセクションには、分析の概要が示されます。プロファイル内に処理の遅い tf.data 入力パイプラインが検出されたかどうかがわかります。検出されている場合は、最も多い入力バウンドのホストと、その中で最も遅い入力パイプラインが最大レイテンシとともに表示されます。最も重要なのは、入力パイプラインのどの部分がボトルネックであり、それをどのように修正するかと示しているところです。ボトルネックの情報には、イテレータの種類とそのロング名が示されます。

tf.data イテレータのロング名の読み取り方

ロング名は、Iterator::<Dataset_1>::...::<Dataset_n> のような形式です。ロング名内の <Dataset_n> は、イテレータの種類に一致しており、ロング名の他のデータセットは、下流の変換を表します。

たとえば、次の入力パイプラインデータセットを見てみましょう。

dataset = tf.data.Dataset.range(10).map(lambda x: x).repeat(2).batch(5)

上記のデータセットから、イテレータのロング名は次のように読み取れます。

イテレータの種類 ロング名
範囲 Iterator::Batch::Repeat::Map::Range
マップ Iterator::Batch::Repeat::Map
反復 Iterator::Batch::Repeat
バッチ Iterator::Batch

全入力パイプラインのサマリー

image

このセクションには、全ホストのすべての入力パイプラインの概要が示されます。通常、入力パイプラインは 1 つです。分散ストラテジーを使用している場合、プログラムの tf.data コードを実行しているホストにゅうりょくパイプラインが 1 つと、そのホスト入力パイプラインからデータを取得してデバイスに転送しているデバイス入力パイプラインが複数あります。

入力パイプラインごとに、実行時間の統計が表示されます。50 μs より長くかかる呼び出しは、遅いと見なされます。

入力パイプラインのグラフ

image

このセクションには、入力パイプラインのグラフが実行時間と共に示されます。「Host」と「Input Pipeline」を使って、どのホストと入力パイプラインを表示するかを選択できます。入力パイプラインの実行は、実行時間別に降順で並べ替えられており、この順序は「Rank」を使って選択できます。

image

重要なパスにあるノードは太いアウトラインで示されます。ボトルネックノードは重要なパスにある、それ自体の処理に最も時間のかかったノードで、赤いアウトラインで示されます。その他の重要でないノードは、グレーの破線で示されます。

各ノードの「Start Time」は、実行の開始時刻を示します。入力パイプラインにバッチがある場合などは、同一のノードが何度も実行されることがありますが、その場合の開始時刻は、最初に実行されたときの時刻です。

「Total Duration」を実行の実測時間です。何度も実行されている場合の実測時間は、各実行の実測時間の合計です。

「Self Time」は直下の子ノードと重複した時間を除く「Total Time」です。

「# Calls」は、入力パイプラインが実行された回数です。

パフォーマンスデータの収集

TensorFlow プロファイラは、TensorFlow モデルのホストアクティビティと GPU トレースを収集します。プロファイラは、プログラムモードかサンプリングモードのいずれかでパフォーマンスデータを収集するように構成できます。

プロファイリング API

次の API を使用してプロファイリングを実行できます。

  • TensorBoard Keras のコールバックを使用したプログラムモード(tf.keras.callbacks.TensorBoard

    # Profile from batches 10 to 15
    tb_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir,
                                                 profile_batch='10, 15')
    
    # Train the model and use the TensorBoard Keras callback to collect
    # performance profiling data
    model.fit(train_data,
              steps_per_epoch=20,
              epochs=5,
              callbacks=[tb_callback])
    
  • tf.profiler 関数 API を使用したプログラムモード

    tf.profiler.experimental.start('logdir')
    # Train the model here
    tf.profiler.experimental.stop()
    
  • コンテキストマネージャを使用したプログラムモード

    with tf.profiler.experimental.Profile('logdir'):
        # Train the model here
        pass
    

注意: プロファイラを長時間実行すると、メモリ不足になる可能性があります。一度にプロファイリングするのは 10 ステップまでにすることをお勧めします。初期化のオーバーヘッドによる精度低下を回避するため、最初の数バッチはプロファイリングを避けてください。

  • サンプリングモード - tf.profiler.experimental.server.start()を使用してオンデマンドプロファイリングを実行し、gRPC サーバーを起動して TensorFlow モデルを実行します。gRPC サーバーを起動してモデルを実行したら、TensorBoard プロファイルプラグインの[プロファイルの Capture Profile ボタンを使用してプロファイルをキャプチャできます。まだ実行されていない場合は、上記の「プロファイラのインストール」セクションのスクリプトを使用して TensorBoard インスタンスを起動してください。

    以下に例を示します。

    # Start a profiler server before your model runs.
    tf.profiler.experimental.server.start(6009)
    # (Model code goes here).
    #  Send a request to the profiler server to collect a trace of your model.
    tf.profiler.experimental.client.trace('grpc://localhost:6009',
                                          'gs://your_tb_logdir', 2000)
    

    複数のワーカーのプロファイリング例を以下に示します。

    # E.g. your worker IP addresses are 10.0.0.2, 10.0.0.3, 10.0.0.4, and you
    # would like to profile for a duration of 2 seconds.
    tf.profiler.experimental.client.trace(
        'grpc://10.0.0.2:8466,grpc://10.0.0.3:8466,grpc://10.0.0.4:8466',
        'gs://your_tb_logdir',
        2000)
    

<img src="./images/tf_profiler/capture_profile.png" width="400", height="450">

以下の項目を指定するには、Capture Profile ダイアログを使用します。

  • プロファイルサービス URL または TPU 名のカンマ区切りのリスト
  • プロファイリング期間
  • デバイス、ホスト、Python 関数呼び出しのトレースレベル
  • 初回失敗時にプロファイラにプロファイルのキャプチャを再試行させる回数

カスタムトレーニングループのプロファイリング

TensorFlow コードでカスタムトレーニングループのプロファイルを作成するには、tf.profiler.experimental.Trace API を使用してトレーニングループをインストルメント化し、プロファイラのステップの範囲を示してください。name 引数はステップ名の接頭辞として使用され、step_num キーワード引数はステップ名に追加され、_r キーワード引数はこのトレース イベントをステップ イベントとしてプロファイラに処理させます。

以下に例を示します。

for step in range(NUM_STEPS):
    with tf.profiler.experimental.Trace('train', step_num=step, _r=1):
        train_data = next(dataset)
        train_step(train_data)

これにより、プロファイラのステップごとのパフォーマンス分析が有効になり、ステップイベントがトレースビューアに表示されるようになります。

入力パイプラインで正確な分析を行うため、tf.profiler.experimental.Trace コンテキスト内にデータセットイテレータを必ず含めるようにしてください。

以下のコードスニペットはアンチパターンです。

警告: このコードにより、不正確な入力パイプライン分析が実行されます。

for step, train_data in enumerate(dataset):
    with tf.profiler.experimental.Trace('train', step_num=step, _r=1):
        train_step(train_data)

プロファイリングの使用事例

プロファイラは、4 種類の軸に沿って多数の使用事例をカバーしています。これらの組み合わせの中には、現在サポートされているものもあれば、今後の追加が予定されているものもあります。次に一部の使用事例を示します。

  • ローカルプロファイリングとリモートプロファイリング: これら 2 つは、プロファイリング環境を設定するための一般的な方法です。ローカルプロファイリングでは、モデルが実行されているのと同じマシン(GPU を備えたローカルのワークステーションなど)でプロファイリング API が呼び出されます。リモートプロファイリングでは、モデルが実行されているマシンとは異なるマシン(Cloud TPU 上など)でプロファイリング API が呼び出されます。
  • 複数のワーカーのプロファイリング: TensorFlow の分散トレーニング機能を使用すると、複数のマシンをプロファイリングできます。
  • ハードウェアプラットフォーム: CPU、GPU、TPU のプロファイリング。

以下の表に、TensorFlow のさまざまなプロファイリング API がサポートしている上記の使用事例を簡単にまとめています。

| プロファイリング API | ローカル | リモート | 複数 | ハードウェア | : : : : ワーカー : プラットフォーム : | :--------------------------- | :-------- | :-------- | :-------- | :-------- | | TensorBoard Keras | サポート対象 | サポート | サポート | CPU、GPU | : コールバック : : 対象外 : 対象外 : : | tf.profiler.experimental | サポート対象 | サポート | サポート | CPU、GPU | : start/stop API : : 対象外 : 対象外 : : | tf.profiler.experimental | サポート対象 | サポート対象 | サポート対象 | CPU、GPU, | : client.trace API : : : : TPU : | コンテキストマネージャ API | サポート対象 | サポート | サポート | CPU、GPU | : : : 対象外 : 対象外 : :

最適なモデルパフォーマンスのベストプラクティス

TensorFlow モデルに適用可能な次の推奨事項を参照し、最適なパフォーマンスを実現してください。

一般的にはデバイス上ですべての変換を実行し、cuDNN や Intel MKL などのご使用のプラットフォームと互換性のあるライブラリの最新バージョンを使用するようにしてください。

入力データパイプラインの最適化

データ入力パイプラインを効率化してデバイスのアイドル時間を削減すると、モデルの実行速度を大幅に向上させることができます。データ入力パイプラインの効率を上げるため、こちらで説明する次のベストプラクティスを採用することを検討してください。

  • データをプリフェッチする
  • データ抽出を並列化する
  • データ変換を並列化する
  • データをメモリにキャッシュする
  • ユーザー定義関数をベクトル化する
  • 変換を適用する際のメモリ使用量を削減する

また、合成データを使用してモデルを実行し、入力パイプラインがパフォーマンスのボトルネックになっていないかどうかを確認してください。

デバイスのパフォーマンス改善

  • トレーニングのミニバッチサイズ(トレーニングループの 1 回のイテレーションでデバイスごとに使用されるトレーニングサンプルの数)を大きくする。
  • TensorFlow 統計を使用し、デバイス上の演算がどの程度効率的に実行されているかを確認する。
  • tf.function を使用して演算を実行し、必要に応じて experimental_compile フラグを有効にする。
  • ステップ間でホスト側の Python 演算を最小化し、コールバックを減らす。すべてのステップではなく、数ステップごとにメトリックを計算する。
  • デバイスの演算ユニットをビジー状態に保つ。
  • 複数のデバイスに対して並列にデータを送信する。
  • チャネルを優先するようにデータレイアウトを最適化する(NHWC の代わりに NCHW など)。NVIDIA® V100 のような特定の GPU は NHWC データレイアウトでより高速に動作します。
  • IEEE が規定した半精度浮動小数点形式である fp16、または Brain 浮動小数点である bfloat16 形式などの 16 ビット数値表現を使用することを検討する。
  • Keras 混合精度 API の使用を検討する。
  • GPU でトレーニングする場合は、TensorCore を利用する。精度が fp16 で、入出力の次元が 8 または 16 で割り切れる場合(int8の場合)、GPU カーネルは TensorCore を使用する。

追加リソース

既知の制限

TensorFlow 2.2 と TensorFlow 2.3 におけるマルチ GPU のプロファイリング

TensorFlow 2.2 と 2.3 では、シングルホストシステムのみのマルチ GPU プロファイリングがサポートされています。マルチホストシステムの GPU プロファイリングはサポートされていません。マルチワーカー GPU 構成のプロファイリングを行うには、各ワーカーを個別にプロファイルする必要があります。TensorFlow 2.4 では、tf.profiler.experimental.trace API を使って複数のワーカーをプロファイルすることが可能です。

CUDA® Toolkit 10.2 以降では、マルチ GPU のプロファイリングが必要です。TensorFlow 2.2 と 2.3 では、CUDA® Toolkit のバージョン 10.1 までをサポートしているため、libcudart.so.10.1libcupti.so.10.1 にシンボリックリンクを作成してください。

sudo ln -s /usr/local/cuda/lib64/libcudart.so.10.2 /usr/local/cuda/lib64/libcudart.so.10.1
sudo ln -s /usr/local/cuda/extras/CUPTI/lib64/libcupti.so.10.2 /usr/local/cuda/extras/CUPTI/lib64/libcupti.so.10.1