質問があります? TensorFlowフォーラム訪問フォーラムでコミュニティとつながる

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

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

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

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

Cloud TPUでのモデルのパフォーマンスをプロファイリングする場合は、 CloudTPUガイドを参照してください

プロファイラーとGPUの前提条件をインストールします

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

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

  1. TensorFlowGPUサポートソフトウェア要件に記載されているNVIDIA®GPUドライバーとCUDA®ツールキットの要件を満たします
  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 DeveloperDocsを参照してください。

Docker環境でのCUPTI特権の問題を解決するには、

docker run option '--privileged=true'

プロファイラーツール

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

プロファイラーには、パフォーマンス分析に役立つツールがいくつかあります。

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

概要ページ

概要ページには、プロファイルの実行中にモデルがどのように実行されたかのトップレベルのビューが表示されます。このページには、ホストとすべてのデバイスの概要ページと、モデルトレーニングのパフォーマンスを向上させるためのいくつかの推奨事項が表示されます。 [ホスト]ドロップダウンで個々のホストを選択することもできます。

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

画像

  • パフォーマンスの概要-モデルのパフォーマンスの概要を表示します。パフォーマンスの概要には2つの部分があります。

    1. ステップ時間の内訳-平均ステップ時間を、時間が費やされた場所の複数のカテゴリに分類します。

      • コンパイル-カーネルのコンパイルに費やされた時間
      • 入力-入力データの読み取りに費やされた時間
      • 出力-出力データの読み取りに費やされた時間
      • カーネルの起動-ホストがカーネルを起動するために費やした時間
      • ホストの計算時間
      • デバイス間の通信時間
      • デバイス上の計算時間
      • Pythonオーバーヘッドを含む他のすべて
    2. デバイス計算の精度-16ビットおよび32ビットの計算を使用するデバイス計算時間の割合を報告します

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

  • デバイスでの上位10のTensorFlow操作-最も長く実行されたデバイス上の操作を表示します。

    各行には、操作の自己時間(すべての操作にかかった時間のパーセンテージとして)、累積時間、カテゴリ、および名前が表示されます。

  • 実行環境-以下を含むモデル実行環境の概要を表示します。

    • 使用されたホストの数
    • デバイスタイプ(GPU / TPU)
    • デバイスコアの数
  • 次のステップの推奨事項-モデルが入力バインドされたときにレポートし、モデルのパフォーマンスのボトルネックを見つけて解決するために使用できるツールを推奨します

入力パイプラインアナライザー

TensorFlowプログラムがファイルからデータを読み取ると、パイプライン方式でTensorFlowグラフの上部から開始されます。読み取りプロセスは、直列に接続された複数のデータ処理ステージに分割され、1つのステージの出力が次のステージへの入力になります。このデータ読み取りシステムは、入力パイプラインと呼ばれます

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

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

非効率的な入力パイプラインは、アプリケーションの速度を大幅に低下させる可能性があります。アプリケーションが入力パイプラインにかなりの時間を費やしている場合、そのアプリケーションは入力バウンドと見なされます。入力パイプラインアナライザーから得られた洞察を使用して、入力パイプラインが非効率的な場所を理解します。

入力パイプラインアナライザーは、プログラムが入力にバインドされているかどうかを即座に通知し、デバイス側とホスト側の分析をガイドして、入力パイプラインの任意の段階でパフォーマンスのボトルネックをデバッグします。

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

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

入力パイプラインアナライザーを開くには、[プロファイル]を選択し、[ツール]ドロップダウンから[ input_pipeline_analyzer ]を選択します。

画像

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

  1. 要約-アプリケーションが入力バウンドであるかどうか、およびバインドされている場合はその量に関する情報を使用して、入力パイプライン全体を要約します
  2. デバイス側の分析-デバイスのステップ時間や、各ステップでコア間で入力データを待機するために費やされたデバイス時間の範囲など、詳細なデバイス側の分析結果を表示します
  3. ホスト側の分析-ホストでの入力処理時間の内訳を含む、ホスト側での詳細な分析を表示します

入力パイプラインの概要

概要は、ホストからの入力を待機するために費やされたデバイス時間のパーセンテージを提示することにより、プログラムが入力にバインドされているかどうかを報告します。インストルメント化された標準の入力パイプラインを使用している場合、ツールは入力処理時間のほとんどが費やされた場所を報告します。

デバイス側の分析

デバイス側の分析は、デバイスとホストで費やされた時間、およびホストからの入力データの待機に費やされたデバイス時間に関する洞察を提供します。

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

ホスト側の分析

ホスト側の分析では、ホストでの入力処理時間( tf.data API opsに費やされた時間)の内訳がいくつかのカテゴリに報告されます。

  • オンデマンドでファイルからデータを読み取る-キャッシュ、プリフェッチ、インターリーブなしでファイルからデータを読み取るために費やされた時間
  • 事前にファイルからデータを読み取る-キャッシュ、プリフェッチ、インターリーブなど、ファイルの読み取りに費やされた時間
  • データの前処理-画像の解凍などの前処理操作に費やされた時間
  • デバイスに転送されるデータのエンキュー-データをデバイスに転送する前に、データをインフィードキューに入れるのに費やされた時間

[入力操作の統計]を展開して、個々の入力操作の統計と、実行時間ごとに分類されたそれらのカテゴリを表示します。

画像

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

  1. 入力操作-入力操作のTensorFlow操作名を表示します
  2. カウント-プロファイリング期間中のop実行のインスタンスの総数を示します
  3. 合計時間(ミリ秒)-これらの各インスタンスに費やされた時間の累積合計を表示します
  4. 合計時間%-入力処理に費やされた合計時間の一部として、操作に費やされた合計時間を表示します
  5. 合計セルフ時間(ミリ秒単位)-これらの各インスタンスで費やされたセルフ時間の累積合計を示します。ここでの自己時間は、関数本体内で費やされた時間を測定します。ただし、関数が呼び出す関数で費やされた時間は除きます。
  6. 合計自己時間% 。入力処理に費やされた合計時間の一部として合計自己時間を表示します
  7. カテゴリ。入力操作の処理カテゴリを表示します

TensorFlow統計

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

画像

このツールは、パフォーマンス情報を2つのペインに表示します。

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

    1. ホスト上の各操作の自己実行時間の分布
    2. ホスト上の各opタイプの自己実行時間の分布
    3. デバイス上の各操作の自己実行時間の分布
    4. デバイス上の各opタイプの自己実行時間の分布
  • 下のペインには、TensorFlow操作に関するデータをレポートするテーブルが表示されます。操作ごとに1行、データの種類ごとに1列です(列の見出しをクリックして列を並べ替えます)。上部ペインの右側にある[CSVとしてエクスポート]ボタンをクリックして、このテーブルのデータをCSVファイルとしてエクスポートします。

    ご了承ください:

    • いずれかのオペレーションに子オペレーションがある場合:

      • オペレーションの「累積」時間の合計には、子オペレーション内で費やされた時間が含まれます。

      • オペレーションの「自己」時間の合計には、子オペレーション内で費やされた時間は含まれません。

    • ホストでopが実行される場合:

      • 操作によって発生したデバイスの合計セルフタイムのパーセンテージは0になります
      • この操作までのデバイスの合計セルフタイムの累積パーセンテージは0になります
    • デバイスで操作が実行される場合:

      • この操作によって発生したホストの合計セルフタイムの割合は0になります
      • この操作までのホストでの合計セルフタイムの累積パーセンテージは0になります

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

トレースビューア

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

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

トレースビューアを使用すると、モデルのパフォーマンスの問題を特定し、それらを解決するための手順を実行できます。たとえば、大まかに言えば、入力トレーニングとモデルトレーニングのどちらが大部分の時間を費やしているかを特定できます。ドリルダウンすると、実行に最も時間がかかる操作を特定できます。トレースビューアは、デバイスごとに100万イベントに制限されていることに注意してください。

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

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

画像

この画面には、次の主要な要素が含まれています。

  1. タイムラインペイン-デバイスとホストが時間の経過とともに実行した操作を表示します
  2. 詳細ペイン-タイムラインペインで選択された操作の追加情報を表示します

タイムラインペインには、次の要素が含まれています。

  1. トップバー-さまざまな補助コントロールが含まれています
  2. 時間軸-トレースの開始を基準にした時間を表示します
  3. セクションとトラックのラベル-各セクションには複数のトラックが含まれ、左側に三角形があり、クリックしてセクションを展開したり折りたたんだりできます。システム内の処理要素ごとに1つのセクションがあります
  4. ツールセレクター-ズーム、パン、選択、タイミングなど、トレースビューアを操作するためのさまざまなツールが含まれています。タイミングツールを使用して、時間間隔をマークします。
  5. イベント-これらは、操作が実行された時間、またはトレーニングステップなどのメタイベントの期間を示します
セクションとトラック

トレースビューアには、次のセクションが含まれています。

  • デバイスチップとチップ内のデバイスノードの番号でラベル付けされた、デバイスノードごとの1つのセクション(たとえば、 /device:GPU:0 (pid 0) )。各デバイスノードセクションには、次のトラックが含まれています。
    • ステップ-デバイスで実行されていたトレーニングステップの期間を表示します
    • TensorFlowOps- 。デバイスで実行された操作を表示します
    • XLA Ops- XLAが使用されるコンパイラである場合にデバイスで実行されたXLA操作(ops)を表示します(各TensorFlow opは1つまたは複数のXLAopsに変換されます。XLAコンパイラはXLAopsをデバイスで実行されるコードに変換します)。
  • 「ホストスレッド」というラベルの付いた、ホストマシンのCPUで実行されているスレッドの1つのセクション。このセクションには、CPUスレッドごとに1つのトラックが含まれています。セクションラベルの横に表示される情報は無視してかまいません。
イベント

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

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

画像

GPUカーネル統計

このツールは、すべてのGPUアクセラレーションカーネルのパフォーマンス統計と元の操作を表示します。

画像

このツールは、次の2つのペインに情報を表示します。

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

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

    • カーネルと操作のペアでグループ化された合計経過GPU期間の降順でのランク
    • 起動されたカーネルの名前
    • カーネルが使用するGPUレジスタの数
    • 使用される共有(静的+動的共有)メモリの合計サイズ(バイト単位)
    • blockDim.x, blockDim.y, blockDim.zとして表されるブロック次元
    • gridDim.x, gridDim.y, gridDim.zとして表されるグリッド寸法
    • オペレーションがTensorCoresを使用する資格があるかどうか
    • カーネルにTensorCore命令が含まれているかどうか
    • このカーネルを起動したopの名前
    • このカーネルと操作のペアの発生数
    • 経過したGPUの合計時間(マイクロ秒単位)
    • マイクロ秒単位の平均経過GPU時間
    • マイクロ秒単位の最小経過GPU時間
    • マイクロ秒単位の最大経過GPU時間

メモリプロファイルツール

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

  • ピークメモリ使用量とそれに対応するTensorFlowopsへのメモリ割り当てを特定することにより、メモリ不足(OOM)の問題をデバッグします。マルチテナンシー推論を実行するときに発生する可能性のあるOOMの問題をデバッグすることもできます
  • デバッグメモリの断片化の問題

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

  1. メモリプロファイルの概要
  2. メモリタイムライングラフ
  3. メモリ内訳表

メモリプロファイルの概要

このセクションには、以下に示すように、TensorFlowプログラムのメモリプロファイルの概要が表示されます。

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

  1. メモリID-使用可能なすべてのデバイスメモリシステムを一覧表示するドロップダウン。ドロップダウンから表示するメモリシステムを選択します
  2. #Allocation-プロファイリング間隔中に行われたメモリ割り当ての数
  3. #Deallocation-プロファイリング間隔でのメモリの割り当て解除の数
  4. メモリ容量-選択したメモリシステムの合計容量(GiB単位)
  5. ピークヒープ使用量-モデルの実行開始以降のピークメモリ使用量(GiB単位)
  6. ピークメモリ使用量-プロファイリング間隔でのピークメモリ使用量(GiB単位)。このフィールドには、次のサブフィールドが含まれています。
    1. タイムスタンプ-タイムライングラフでメモリ使用量のピークが発生したときのタイムスタンプ
    2. スタック予約-スタックに予約されているメモリの量(GiB単位)
    3. ヒープ割り当て-ヒープに割り当てられたメモリの量(GiB単位)
    4. 空きメモリ-空きメモリの量(GiB単位)。メモリ容量は、スタック予約、ヒープ割り当て、および空きメモリの合計です。
    5. 断片化-断片化の割合(低いほど良い)。これは、(1-空きメモリの最大チャンクのサイズ/合計空きメモリ)のパーセンテージとして計算されます。

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

このセクションには、メモリ使用量(GiB単位)と時間に対する断片化の割合(ミリ秒単位)のプロットが表示されます。

画像

X軸は、プロファイリング間隔のタイムライン(ミリ秒単位)を表します。左側のY軸はメモリ使用量(GiB単位)を表し、右側のY軸は断片化の割合を表します。 X軸の各時点で、合計メモリは、スタック(赤)、ヒープ(オレンジ)、および空き(緑)の3つのカテゴリに分類されます。特定のタイムスタンプにカーソルを合わせると、その時点でのメモリ割り当て/割り当て解除イベントの詳細が次のように表示されます。

画像

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

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

メモリ内訳表

この表は、プロファイリング間隔のピークメモリ使用量の時点でのアクティブなメモリ割り当てを示しています。

画像

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

  • オペレーション名-TensorFlowオペレーションの名前
  • 割り当てサイズ(GiB)-この操作に割り当てられたメモリの合計量
  • 要求されたサイズ(GiB)-この操作で要求されたメモリの合計量
  • オカレンス-この操作の割り当て数
  • リージョンタイプ-この割り当てられたメモリの対象となるデータエンティティタイプ。可能な値は、一時的なtemp 、アクティベーションとグラデーションのoutput 、および重みと定数のpersist / dynamicです。
  • データ型-テンソル要素型
  • 形状-割り当てられたテンソルの形状

ポッドビューア

ポッドビューアツールは、すべてのワーカーにわたるトレーニングステップの内訳を表示します。

画像

  • 上部ペインには、ステップ番号を選択するためのスライダーがあります。
  • 下のペインには、積み上げ縦棒グラフが表示されます。これは、上下に配置されたステップタイムカテゴリの内訳の概要です。積み重ねられた各列は、一意のワーカーを表します。
  • 積み重ねられた列にカーソルを合わせると、左側のカードにステップの内訳の詳細が表示されます。

tf.dataボトルネック分析

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

次の手順に従ってボトルネックを検出します。

  1. 最も入力が多いホストを見つけます。
  2. tf.data入力パイプラインの最も遅い実行を見つけます。
  3. プロファイラートレースから入力パイプライングラフを再構築します。
  4. 入力パイプライングラフでクリティカルパスを見つけます。
  5. クリティカルパス上で最も遅い変換をボトルネックとして特定します。

UIは、パフォーマンス分析の概要、すべての入力パイプラインの概要、および入力パイプライングラフの3つのセクションに分かれています。

パフォーマンス分析の要約

画像

このセクションでは、分析の概要を説明します。低速の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
バッチイテレータ::バッチ

すべての入力パイプラインの概要

画像

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

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

入力パイプライングラフ

画像

このセクションには、実行時間情報を含む入力パイプライングラフが表示されます。 「ホスト」と「入力パイプライン」を使用して、表示するホストと入力パイプラインを選択できます。入力パイプラインの実行は、実行時間の降順で並べ替えられ、「ランク」を使用して選択できます。

画像

クリティカルパス上のノードには太字のアウトラインがあります。クリティカルパス上でセルフタイムが最も長いノードであるボトルネックノードには、赤い輪郭が表示されます。他の重要ではないノードには、灰色の破線の輪郭があります。

各ノードの「開始時刻」は、実行の開始時刻を示します。たとえば、入力パイプラインにバッチがある場合、同じノードが複数回実行される可能性があります。複数回実行する場合は、最初の実行の開始時刻になります。

「合計時間」は、実行の実時間です。複数回実行された場合は、すべての実行のウォール時間の合計です。

「自己時間」は、直接の子ノードと重複する時間のない「合計時間」です。

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

パフォーマンスデータを収集する

TensorFlow Profilerは、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
    

  • サンプリングモードtf.profiler.experimental.server.start()を使用してオンデマンドプロファイリングを実行し、TensorFlowモデルの実行でgRPCサーバーを起動します。 gRPCサーバーを起動してモデルを実行した後、TensorBoardプロファイルプラグインの[プロファイルのキャプチャ]ボタンを使用してプロファイルをキャプチャできます。 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)
    

[プロファイルキャプチャ]ダイアログを使用して、以下を指定します。

  • プロファイルサービスの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つの一般的な方法です。ローカルプロファイリングでは、プロファイリングAPIは、モデルが実行しているのと同じマシンで呼び出されます。たとえば、GPUを備えたローカルワークステーションです。リモートプロファイリングでは、プロファイリングAPIは、モデルが実行されているマシンとは別のマシン(Cloud TPUなど)で呼び出されます。
  • 複数のワーカーのプロファイリング:TensorFlowの分散トレーニング機能を使用すると、複数のマシンのプロファイリングを行うことができます。
  • ハードウェアプラットフォーム:プロファイルCPU、GPU、およびTPU。

以下の表は、上記のユースケースのうち、TensorFlowのさまざまなプロファイリングAPIでサポートされているものの概要を示しています。

プロファイリングAPI地元リモート複数の労働者ハードウェアプラットフォーム
TensorBoardKerasコールバックサポートされていますサポートされていませんサポートされていませんCPU、GPU
tf.profiler.experimental start / stop APIサポートされていますサポートされていませんサポートされていませんCPU、GPU
tf.profiler.experimental client.trace APIサポートされていますサポートされていますサポートされていますCPU、GPU、TPU
コンテキストマネージャーAPIサポートされていますサポートされていませんサポートされていませんCPU、GPU

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

最適なパフォーマンスを実現するには、TensorFlowモデルに該当する次の推奨事項を使用してください。

一般に、デバイスですべての変換を実行し、プラットフォームにcuDNNやIntelMKLなどの最新の互換性のあるバージョンのライブラリを使用していることを確認します。

入力データパイプラインを最適化する

効率的なデータ入力パイプラインは、デバイスのアイドル時間を短縮することにより、モデルの実行速度を大幅に向上させることができます。データ入力パイプラインをより効率的にするために、ここで詳しく説明する次のベストプラクティスを組み込むことを検討してください。

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

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

デバイスのパフォーマンスを向上させる

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

追加のリソース

既知の制限

TensorFlow2.2およびTensorFlow2.3での複数のGPUのプロファイリング

TensorFlow 2.2および2.3は、単一のホストシステムに対してのみ複数のGPUプロファイリングをサポートします。マルチホストシステムのマルチGPUプロファイリングはサポートされていません。マルチワーカーGPU構成をプロファイリングするには、各ワーカーを個別にプロファイリングする必要があります。 TensorFlow 2.4では、 tf.profiler.experimental.traceを使用して複数のワーカーをプロファイリングできます。

複数のGPUをプロファイリングするには、CUDA®Toolkit10.2以降が必要です。 TensorFlow 2.2および2.3は10.1までのCUDA®Toolkitバージョンのみをサポートするため、 libcudart.so.10.1およびlibcupti.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