トレースを開く前に問いを選ぶ
トレースは具体的な問いに答えるのに適しています。計算がデータを待っているのか、コピーが繰り返されているのか、小さなオペレータが呼ばれすぎているのか。ステップの入力、出力、境界を定義します。トレーニングの場合は、backward、オプティマイザの更新、バッチの読み込みが含まれるかどうかを明示します。推論の場合は、モデルのロードとリクエストを分離します。
正しさが分かっている短いシナリオを維持します。形状、バッチ、精度、モデルのモード、コンパイルの有無、データのソースを記録します。簡略化した入力は挙動の分離に役立つことがありますが、必ずしも完全な負荷を表すものではなくなります。この違いはレポートに記載します。
最終的な単位を固定してください: ステップあたりのミリ秒、または1秒あたりに処理されたサンプル数。イベントの合計は経過時間を置き換えるものではありません。読み取りと転送の境界が同じウィンドウを比較してください。
CPU時間、GPU作業、待機を区別する
CPUは操作を準備して起動し、GPUはそれらを後で実行することがあります。したがってPythonの区間には、起動、待機、またはその両方が含まれる可能性があります。PyTorchのCUDAドキュメントは、正確な測定ではこの非同期性を考慮すべきであり、特に範囲に応じた同期やイベントを用いるべきだと述べています。
GPU 上の特定の処理時間を測定するには、CUDA イベントが適しています。エンドツーエンドのレイテンシには、そのレイテンシに含まれる処理の完了を待ち、リクエスト全体を測定してください。これら2つの単位を混在させないでください。各操作の間に追加された同期は、実際のオーバーラップを排除し、理解しようとしているプログラムそのものを変えてしまう可能性があります。
プロファイラでは、オペレータの自己時間とサブ操作を含む時間は、それぞれ異なる問いに答えるものです。表の行を合計する前にタイムラインを見てください。同時または入れ子になったアクティビティは、互いに重複しない経過時間の部分を表すものではありません。
起動フェーズとアクティブウィンドウを分けて確保する
最初のパスには初期化、読み込み、コンパイルが含まれることがあります。あなたの問いがこの起動に関するものか、すでに安定したフェーズに関するものかを決めます。全体的なものとして提示された平均から初期コストを消すのではなく、使用にとって重要な場合は両方の観察を保持します。
schedule関数は、待機、収集の準備、アクティブウィンドウを区別するのに役立ちます。プロファイラのウォームアップは、あなたのモデルが安定状態に達した証拠ではありません。遭遇する形状やキャッシュの状態も確認します。入力が変動するアプリケーションでは、複数回のイテレーション後に新しいパスに遭遇することがあります。
以下で提案する教育的なスケジュールは、1ステップを待ち、1ステップを準備し、2ステップをキャプチャします。4ステップではメカニズムを説明するには十分ですが、性能分布を確立するには足りません。実際のキャンペーンでは、根拠のあるウィンドウを選び、分析後にプロファイラの外で測定を繰り返します。
提案する例: 読み取り可能な境界を持つ4つのステップ
以下の断片は実行されていません。model、optimizer、loss_fn、loader、device が存在し、モデルが device 上にあり、ローダーが少なくとも4つの x、y のペアのバッチを提供することを前提としています。これは更新を実行するため、重みを保持する必要があるセッションではなく、そのために用意された実験用の状態を使用してください。
各ラベルは CPU での読み取り、転送、トレーニングを分離しています。イテレーターはウィンドウの前に作成されるため、その起動の一部は範囲から除外されます。ファイルは新しい名前で選択され、既存のトレースを上書きしないようにしています。この例は、利用できない GPU 収集を CPU トレースでこっそり GPU 分析として提示する代わりに、拒否します。
step() シグナルは各ステップの後にスケジュールを進めます。公式レシピは、この反復と収集の関係を説明しています。ROCm スタックでは、PyTorch のデバイス名は依然として cuda のままです。ただし、アクセラレーター収集の可用性はビルドとそのツールに依存します。結果に実際に含まれるアクティビティを確認してください。
from pathlib import Path
import torch
from torch.profiler import (
profile, schedule, record_function,
ProfilerActivity, supported_activities,
)
trace = Path("trace-etape.json")
if trace.exists():
raise FileExistsError("新しいトレース名を選択してください")
activities = [ProfilerActivity.CPU]
if device.type == "cuda":
if ProfilerActivity.CUDA not in supported_activities():
raise RuntimeError("このビルドでは GPU 収集を利用できません")
activities.append(ProfilerActivity.CUDA)
iterator = iter(loader)
model.train()
with profile(
activities=activities,
schedule=schedule(wait=1, warmup=1, active=2, repeat=1),
record_shapes=False, profile_memory=False, with_stack=False,
on_trace_ready=lambda p: p.export_chrome_trace(str(trace)),
) as prof:
for _ in range(4):
with record_function("lecture_batch_cpu"):
x, y = next(iterator)
with record_function("transfert"):
x, y = x.to(device), y.to(device)
with record_function("entrainement"):
optimizer.zero_grad(set_to_none=True)
loss = loss_fn(model(x), y)
loss.backward()
optimizer.step()
prof.step()
print(prof.key_averages().table(
sort_by="self_cpu_time_total", row_limit=8,
))観察を検証可能な仮説に変える
まずアクティブウィンドウから始め、期待されるラベルが表示されることを確認します。次にアクティビティ間の空白、コピー、繰り返しを調べます。lecture_batch_cpu での長い待ち時間は入力パイプラインを示唆しますが、ストレージを直接測定しているわけではありません。頻繁なコピーはテンソルの配置を検討するきっかけになりますが、それが不要であることを証明するものではありません。
単一の仮説を立ててから、制御された変更を提案します。たとえば、定数が各ステップで再構築されて転送される場合、結果を変えずにそのライフタイムを複数のステップにまたがらせることができるか確認します。ある演算子が支配的に見える場合は、代替を探す前にその形状と呼び出し回数を調べます。
以下の行は可能な読み取りであり、実行されたトレースから得られた所見ではありません。所要時間や高速化は一切謳っていません。有用な結論は、提案された原因を確認または反証できる次の実験です。
表をスクロールしてすべての列を表示してください。| 考えられる観察 | 仮説 | 次の確認 |
|---|---|---|
| 読み取り中に GPU が無活動 | 入力パイプラインが追いついていない | バッチを事前に準備した同じ計算 |
| 定数の繰り返しコピー | 配置またはライフタイムが不適切 | 一度移動し、出力を確認する |
| 多数の小さな起動 | 断片化された作業 | グループ化と全体コストを検討する |
| 長時間実行される演算子 | 形状またはアルゴリズムが決定要因 | 同じオペレーターとその入力を比較する |
計測のコストと情報を制限する
短くオプションの少ない収集から始めます。形状、スタック、メモリは、質問がそれを求める場合にのみ有効にします。PyTorch API は、これらの情報がコストを追加すると明記しています。形状の収集はテンソルへの参照を保持することさえあります。したがって、詳細なプロファイルはプログラムの所要時間やメモリ使用量を変える可能性があります。
トレースにはオペレーター名、形状、オプションによってはコードパスが含まれることがあります。共有する前に検査してください。ゾーンラベルは、メールアドレス、トークン、プライベートパス、入力内容を含めずにステップを説明する必要があります。環境に適したトレースビューアを選び、収集を自分の管理下に置いてください。
期待されるGPUイベントが存在しない場合、その時間をゼロで埋めないでください。観測されなかったことを示し、収集のサポートを検討してください。ツールにイベントがないことは、計算がなかった証拠にはなりません。
プロファイラを使わずに最適化を検証する
同じ関連する状態から開始し、変更の前後で修正を比較してください。トレーニングでは、追加のステップが重みを変えます。連続して実行された2つのキャプチャは、必ずしも等価な比較にはなりません。コード、パラメータ、開始点を保持しておき、差異を説明できるようにしてください。
次に、詳細な収集を行わずに、同じウォームアップと複数回の実行でシナリオを測定してください。範囲、生の値、そのばらつきを報告してください。局所的な改善はループ全体の中で消えたり、品質を低下させたりする可能性があるため、どちらも意思決定に含める必要があります。
最後に、観測結果を使って実際に必要なリソースを明確にしてください。ご自身のマシンのトレースはKernodeckのオファーをランク付けするものではなく、レンタルしたサーバーのホストCPUやネットワークを証明するものでもありません。GPUの比較には、対象リソースにおける比較可能な負荷、条件、結果が必要です。