0x0.プリアンブル
この翻訳は、https://www.deepspeed.ai/tutorials/pytorch-profiler/ および https://www.deepspeed.ai/tutorials/flops-profiler/ の 2 つのチュートリアル用であり、DeepSpeed トレーニング モデルを使用してベースにすることができます。これら 2 つのチュートリアルでは、プロファイルの作業判断モデルとメモリのボトルネックがどこにあるかを計算します。
0x1. パフォーマンスのデバッグに DeepSpeed で PyTorch Profiler を使用する
元のチュートリアルに対応: https://www.deepspeed.ai/tutorials/pytorch-profiler/
このチュートリアルでは、DeepSpeed で PyTorch Profiler ツール (https://pytorch.org/blog/introducing-pytorch-profiler-the-new-and-improved-performance-tool/) を使用する方法について説明します。
PyTorch Profiler は、大規模な深層学習モデルの正確かつ効率的なパフォーマンス プロファイリングとトラブルシューティングを提供するオープン ソース ツールです。解析結果は.jsonトレースファイルとして出力し、Google Chromeのトレースビューア(chrome://tracing)で確認できます。Microsoft Visual Studio Code の Python 拡張機能は、PyTorch Profiler のサポートを含め、TensorBoard をコード エディターに統合します。詳細については、(https://pytorch.org/tutorials/recipes/recipes/profiler_recipe.html#pytorch-profiler) を参照してください。
プロファイルモデルトレーニングのサイクル
以下は、プロファイラー コンテキスト マネージャーでコードをラップすることによってトレーニング ループをプロファイリングする方法を示しています。プロファイラーは、トレーニング プロセスがステップ (0 から番号付け) で構成されていると想定します。PyTorch Profiler はschedule
、on_trace_ready
、with_stack
などの多くのパラメータを受け入れます。
以下の例では、アナライザーは前の5
ステップをスキップし、次の2
ステップをウォームアップとして使用し、次の6
ステップを記録します。repeat
設定されているため2
、アナライザーは 2 サイクル後に記録を停止します (ここでのサイクルとは、アクティブなステップ数を繰り返すことを意味しますrepeat
)。のschedule
詳しい使用方法については、「プロファイラーを使用して長時間実行ジョブを分析する」 (https://pytorch.org/tutorials/recipes/recipes/profiler_recipe.html#using-profiler-to-analyze-long-running-jobs) を参照してください。
from torch.profiler import profile, record_function, ProfilerActivity
with torch.profiler.profile(
schedule=torch.profiler.schedule(
wait=5, # During this phase profiler is not active.
warmup=2, # During this phase profiler starts tracing, but the results are discarded.
active=6, # During this phase profiler traces and records data.
repeat=2), # Specifies an upper bound on the number of cycles.
on_trace_ready=tensorboard_trace_handler,
with_stack=True # Enable stack tracing, adds extra profiling overhead.
) as profiler:
for step, batch in enumerate(data_loader):
print("step:{}".format(step))
#forward() method
loss = model_engine(batch)
#runs backpropagation
model_engine.backward(loss)
#weight update
model_engine.step()
profiler.step() # Send the signal to the profiler that the next step has started.
任意のコード範囲をマークします
record_function
コンテキスト マネージャーを使用して、任意のユーザー指定のコード範囲をマークできます。たとえば、次のコードは「model_forward」をラベルとしてマークします。
with profile(record_shapes=True) as prof: # record_shapes indicates whether to record shapes of the operator inputs.
with record_function("model_forward"):"
model_engine(inputs)
その後、プロファイル結果で、マークされた「model_forward」の時間がかかっている状況を確認できます。
CPU/GPUアクティビティをプロファイルする
プロファイラーに渡されるアクティビティ パラメーターは、プロファイラー コンテキスト マネージャーでラップされたコード スコープの実行中にプロファイリングされるアクティビティのリストを指定します。
- ProfilerActivity.CPU - PyTorch オペレーター、TorchScript 関数、およびユーザー定義コード タグ (
record_function
)。 - ProfilerActivity.CUDA - デバイス上の CUDA カーネル。CUDA プロファイリングは無視できないオーバーヘッドを課すことに注意してください。
以下の例では、モデルのフォワード パス中に CPU と GPU のアクティビティをプロファイリングし、合計 CUDA 時間でソートされた概要テーブルを出力します。
with profile(activities=[
ProfilerActivity.CPU, ProfilerActivity.CUDA], record_shapes=True) as prof:
with record_function("model_forward"):
model_engine(inputs)
print(prof.key_averages().table(sort_by="cuda_time_total", row_limit=10))
プロファイルのメモリ消費量
PyTorch Profiler に渡すことでprofile_memory=True
、モデル OP の実行中に割り当てられた (または解放された) モデル テンソルによって使用されるメモリの量を記録するメモリ プロファイリング機能が有効になります。例えば:
with profile(activities=[ProfilerActivity.CUDA],
profile_memory=True, record_shapes=True) as prof:
model(inputs)
print(prof.key_averages().table(sort_by="self_cuda_memory_usage", row_limit=10))
0x2。フロップスプロファイラー
元のチュートリアルに対応: https://www.deepspeed.ai/tutorials/flops-profiler/
このチュートリアルでは、DeepSpeed Flops Profiler を紹介し、その使用例を示します。
概要
ハードウェア リソースを効率的に利用することは、優れたパフォーマンスを実現するために重要ですが、既存の大規模モデルのトレーニングと推論の実装では、パフォーマンスの非効率性を検出するのが難しく、特定のモジュール コンポーネントが原因であることがよくあります。DeepSpeed Flops Profiler は、ユーザーがモデルとそのサブモジュールのトレーニング/推論速度 (レイテンシ、スループット) と効率 (1 秒あたりの浮動小数点演算、つまり FLOPS) を簡単に測定できるようにし、既存の実装における非効率性を排除することを目的としています。
以下は、A100 GPU でバッチ サイズ 80 を使用した BERT-Large (NVIDIA) からの出力例です。
-------------------------- DeepSpeed Flops Profiler --------------------------
Profile Summary at step 10:
Notations:
data parallel size (dp_size), model parallel size(mp_size),
number of parameters (params), number of multiply-accumulate operations(MACs),
number of floating-point operations (flops), floating-point operations per second (FLOPS),
fwd latency (forward propagation latency), bwd latency (backward propagation latency),
step (weights update latency), iter latency (sum of fwd, bwd and step latency)
world size: 1
data parallel size: 1
model parallel size: 1
batch size per GPU: 80
params per gpu: 336.23 M
params of model = params per GPU * mp_size: 336.23 M
fwd MACs per GPU: 3139.93 G
fwd flops per GPU: 6279.86 G
fwd flops of model = fwd flops per GPU * mp_size: 6279.86 G
fwd latency: 76.67 ms
bwd latency: 108.02 ms
fwd FLOPS per GPU = fwd flops per GPU / fwd latency: 81.9 TFLOPS
bwd FLOPS per GPU = 2 * fwd flops per GPU / bwd latency: 116.27 TFLOPS
fwd+bwd FLOPS per GPU = 3 * fwd flops per GPU / (fwd+bwd latency): 102.0 TFLOPS
step latency: 34.09 us
iter latency: 184.73 ms
samples/second: 433.07
----------------------------- Aggregated Profile per GPU -----------------------------
Top modules in terms of params, MACs or fwd latency at different model depths:
depth 0:
params - {
'BertForPreTrainingPreLN': '336.23 M'}
MACs - {
'BertForPreTrainingPreLN': '3139.93 GMACs'}
fwd latency - {
'BertForPreTrainingPreLN': '76.39 ms'}
depth 1:
params - {
'BertModel': '335.15 M', 'BertPreTrainingHeads': '32.34 M'}
MACs - {
'BertModel': '3092.96 GMACs', 'BertPreTrainingHeads': '46.97 GMACs'}
fwd latency - {
'BertModel': '34.29 ms', 'BertPreTrainingHeads': '3.23 ms'}
depth 2:
params - {
'BertEncoder': '302.31 M', 'BertLMPredictionHead': '32.34 M'}
MACs - {
'BertEncoder': '3092.88 GMACs', 'BertLMPredictionHead': '46.97 GMACs'}
fwd latency - {
'BertEncoder': '33.45 ms', 'BertLMPredictionHead': '2.61 ms'}
depth 3:
params - {
'ModuleList': '302.31 M', 'Embedding': '31.79 M', 'Linear': '31.26 M'}
MACs - {
'ModuleList': '3092.88 GMACs', 'Linear': '36.23 GMACs'}
fwd latency - {
'ModuleList': '33.11 ms', 'BertPredictionHeadTransform': '1.83 ms''}
depth 4:
params - {'BertLayer': '302.31 M', 'LinearActivation': '1.05 M''}
MACs - {
'BertLayer': '3092.88 GMACs', 'LinearActivation': '10.74 GMACs'}
fwd latency - {
'BertLayer': '33.11 ms', 'LinearActivation': '1.43 ms'}
depth 5:
params - {
'BertAttention': '100.76 M', 'BertIntermediate': '100.76 M'}
MACs - {
'BertAttention': '1031.3 GMACs', 'BertIntermediate': '1030.79 GMACs'}
fwd latency - {
'BertAttention': '19.83 ms', 'BertOutput': '4.38 ms'}
depth 6:
params - {
'LinearActivation': '100.76 M', 'Linear': '100.69 M'}
MACs - {
'LinearActivation': '1030.79 GMACs', 'Linear': '1030.79 GMACs'}
fwd latency - {
'BertSelfAttention': '16.29 ms', 'LinearActivation': '3.48 ms'}
------------------------------ Detailed Profile per GPU ------------------------------
Each module profile is listed after its name in the following order:
params, percentage of total params, MACs, percentage of total MACs, fwd latency, percentage of total fwd latency, fwd FLOPS
BertForPreTrainingPreLN(
336.23 M, 100.00% Params, 3139.93 GMACs, 100.00% MACs, 76.39 ms, 100.00% latency, 82.21 TFLOPS,
(bert): BertModel(
335.15 M, 99.68% Params, 3092.96 GMACs, 98.50% MACs, 34.29 ms, 44.89% latency, 180.4 TFLOPS,
(embeddings): BertEmbeddings(...)
(encoder): BertEncoder(
302.31 M, 89.91% Params, 3092.88 GMACs, 98.50% MACs, 33.45 ms, 43.79% latency, 184.93 TFLOPS,
(FinalLayerNorm): FusedLayerNorm(...)
(layer): ModuleList(
302.31 M, 89.91% Params, 3092.88 GMACs, 98.50% MACs, 33.11 ms, 43.35% latency, 186.8 TFLOPS,
(0): BertLayer(
12.6 M, 3.75% Params, 128.87 GMACs, 4.10% MACs, 1.29 ms, 1.69% latency, 199.49 TFLOPS,
(attention): BertAttention(
4.2 M, 1.25% Params, 42.97 GMACs, 1.37% MACs, 833.75 us, 1.09% latency, 103.08 TFLOPS,
(self): BertSelfAttention(
3.15 M, 0.94% Params, 32.23 GMACs, 1.03% MACs, 699.04 us, 0.92% latency, 92.22 TFLOPS,
(query): Linear(1.05 M, 0.31% Params, 10.74 GMACs, 0.34% MACs, 182.39 us, 0.24% latency, 117.74 TFLOPS,...)
(key): Linear(1.05 M, 0.31% Params, 10.74 GMACs, 0.34% MACs, 57.22 us, 0.07% latency, 375.3 TFLOPS,...)
(value): Linear(1.05 M, 0.31% Params, 10.74 GMACs, 0.34% MACs, 53.17 us, 0.07% latency, 403.91 TFLOPS,...)
(dropout): Dropout(...)
(softmax): Softmax(...)
)
(output): BertSelfOutput(
1.05 M, 0.31% Params, 10.74 GMACs, 0.34% MACs, 114.68 us, 0.15% latency, 187.26 TFLOPS,
(dense): Linear(1.05 M, 0.31% Params, 10.74 GMACs, 0.34% MACs, 64.13 us, 0.08% latency, 334.84 TFLOPS, ...)
(dropout): Dropout(...)
)
)
(PreAttentionLayerNorm): FusedLayerNorm(...)
(PostAttentionLayerNorm): FusedLayerNorm(...)
(intermediate): BertIntermediate(
4.2 M, 1.25% Params, 42.95 GMACs, 1.37% MACs, 186.68 us, 0.24% latency, 460.14 TFLOPS,
(dense_act): LinearActivation(4.2 M, 1.25% Params, 42.95 GMACs, 1.37% MACs, 175.0 us, 0.23% latency, 490.86 TFLOPS,...)
)
(output): BertOutput(
4.2 M, 1.25% Params, 42.95 GMACs, 1.37% MACs, 116.83 us, 0.15% latency, 735.28 TFLOPS,
(dense): Linear(4.2 M, 1.25% Params, 42.95 GMACs, 1.37% MACs, 65.57 us, 0.09% latency, 1310.14 TFLOPS,...)
(dropout): Dropout(...)
)
)
...
(23): BertLayer(...)
)
)
(pooler): BertPooler(...)
)
(cls): BertPreTrainingHeads(...)
)
------------------------------------------------------------------------------
DeepSpeed Flops Profiler は、プロファイルの概要で、モデルのパラメーターの数、浮動小数点演算 (フロップ) の数、FLOPS、レイテンシー、サンプル/秒のスループットを出力します。この概要は、現在のモデル実行とハードウェアのピーク パフォーマンスの間のパフォーマンス ギャップを示し、ユーザーがトレーニングまたは推論設定 (ハイパーパラメーター、データ並列処理、モデル並列処理、システム構成など) を調整してより良いパフォーマンスを達成するのに役立ちます。
DeepSpeed Flops Profiler は、さまざまなモデルの深さで重要なモジュール (集約プロファイル) やモデル アーキテクチャ内の特定のモジュール (詳細プロファイル) をプロファイリングすることもできます。これらのプロファイルを通じて、DeepSpeed ユーザーは、モデル全体の複雑さ/パフォーマンスに対する各レイヤーまたはサブモジュールの寄与を理解できます。その後、ユーザーはモデル設計を調整またはリファクタリングして、パフォーマンスを向上させることができます。たとえば、DeepSpeed ユーザーはプロファイラーを使用して、小さなレイヤーを積み重ねた方が大きなレイヤーを積み重ねる場合よりも軽量であるか、パフォーマンスが優れているかを定量化できます。集約された詳細なプロファイルにより、ユーザーはボトルネック モジュールを迅速に特定することもできます。上記の BERT-Large の例では、DeepSpeed Flops Profiler を使用して、BertLayer が最も重要なレイヤーであり、多くのドロップアウト、ソフトマックス、レイヤー ノルム、および線形レイヤー モジュールが含まれていることがわかりました。これらのモジュールはフロップでは重くありませんが、多くの GPU カーネル呼び出しをトリガーし、過剰なメモリ読み取り/書き込みリクエストを作成します。詳細なプロファイルに示されているパターンは、これがカーネル融合に完全に一致していることを示しており、データの移動を減らすために融合トランスフォーマー カーネルを開発しました (https://www.deepspeed.ai/tutorials/bert-pretraining/ を参照)。最適化を適用した後、DeepSpeed Flops Profiler の出力で GPU あたりの FLOPS と全体的なトレーニング サンプル/秒が 25% 向上しました。
DeepSpeed Flops Profiler は、ユーザー コードを変更せずに DeepSpeed ランタイムと一緒に使用することも、DeepSpeed から独立したスタンドアロン パッケージとして使用することもできます。モデルのトレーニングに DeepSpeed を使用する場合、プロファイラーは DeepSpeed 構成ファイル (https://www.deepspeed.ai/docs/config-json/#flops-profiler) で有効にすることができます。Analyzer API はスタンドアロン パッケージとして、トレーニング コードと推論コードの両方で使用できます。DeepSpeed Profiler はまだ開発中であり、現在は初期機能のみが含まれています。さらにエキサイティングな機能が間もなく追加される予定ですので、ご期待ください。
フロップ測定
既存のフロップ計算ツールまたは手法と同様に、DeepSpeed Flops Analyzer はモジュールの順伝播フロップを測定しますが、逆伝播フロップは順伝播フロップの 2 倍と推定されます。PyTorch Op のフロップをカウントする PyTorch Analyzer とは異なり、DeepSpeed Flops Analyzer はモデル内のモジュール内のフロップを測定し、モデルの実行についてのより多くの洞察をユーザーに提供します。フロップス推定部分は ptflops (https://github.com/sovrasov/flops-counter.pytorch) からインスピレーションを得ています。主な違いは、DeepSpeed Flops アナライザーがモジュール レベルで FLOPS 計算を直接サポートするだけでなく、モジュール内の呼び出しをキャプチャしてtorch.nn.functional
フロップを推定します。ParallelTransformerLayerworks
したがって、DeepSpeed Flops アナライザーでは、Megatron-LM の、ParallelSelfAttention
、などのカスタム モジュールをモデルで使用できますRowParallelLinear
。これは、ユーザーがカスタム モジュールごとにカスタム フロップス計算関数を作成する必要がある ptflops とは対照的です。
マルチ GPU、マルチノード、データ並列、モデル並列
DeepSpeed Flops Analyzerは、ワールドサイズ、データ並列サイズ、モデル並列サイズとともにGPUごとの解析結果を出力します。
複数の GPU または複数のノードで実行されるモデルの場合、モデルの並列処理 (たとえば、 Megatron-LM --model-parallel-size
) の変更のみが、浮動小数点オペランドとパラメータ、つまりmodel_parallel_size * flops = total_flops
およびの解析結果に影響しますmodel_parallel_size * parameters = total_parameters
。データの並列サイズまたはワールド サイズ (GPU またはノードの数に関連) は、GPU ごとの解析結果に影響しません。
例
DeepSpeed Flops Analyzer は、DeepSpeed ランタイムと一緒に、またはスタンドアロン パッケージとして使用できます。モデルのトレーニングに DeepSpeed を使用する場合、ユーザーはコードを変更せずに DeepSpeed 構成ファイル (https://www.deepspeed.ai/docs/config-json/#flops-profiler) でプロファイラーを構成できます。DeepSpeed ランタイムの外部でフロップス アナライザーを使用するには、DeepSpeed をインストールし、flops_profiler
パッケージをインポートして API を直接使用します。それぞれの使用方法の例を以下に示します。
DeepSpeed ランタイムで使用するため
モデルのトレーニングに DeepSpeed を使用する場合、アナライザーは DeepSpeed 構成ファイルで構成できます。プロファイラーを使用する場合、明示的な API 呼び出しは必要ありません。アナライザーは、deepspeed の構成 json ファイルに次のフィールドを追加することで有効にできます。詳細については、flops プロファイラー (https://www.deepspeed.ai/docs/config-json/#flops-profiler) を参照してください。
{
"flops_profiler": {
"enabled": true,
"profile_step": 1,
"module_depth": -1,
"top_modules": 1,
"detailed": true,
"output_file": null
}
}
メガトロンLMで使用
DeepSpeed で Megatron-LM を実行する方法については、チュートリアル Megatron-LM を参照してください。
12 層 Megatron-LM モデルの出力例 ( hidden_size = 8192
、num_attention_heads = 32
、batch_size = 1024
、 ) を以下に示しますseq_length = 1024
。
-------------------------- DeepSpeed Flops Profiler --------------------------
Profile Summary at step 10:
Notations:
data parallel size (dp_size), model parallel size(mp_size),
number of parameters (params), number of multiply-accumulate operations(MACs),
number of floating-point operations (flops), floating-point operations per second (FLOPS),
fwd latency (forward propagation latency), bwd latency (backward propagation latency),
step (weights update latency), iter latency (sum of fwd, bwd and step latency)
world size: 1
data parallel size: 1
model parallel size: 1
batch size per GPU: 1024
params per gpu: 1.29 M
params of model = params per GPU * mp_size: 1.29 M
fwd MACs per GPU: 41271.95 G
fwd flops per GPU: 82543.9 G
fwd flops of model = fwd flops per GPU * mp_size: 82543.9 G
fwd latency: 1.89 s
bwd latency: 5.38 s
fwd FLOPS per GPU = fwd flops per GPU / fwd latency: 43.68 TFLOPS
bwd FLOPS per GPU = 2 * fwd flops per GPU / bwd latency: 30.7 TFLOPS
fwd+bwd FLOPS per GPU = 3 * fwd flops per GPU / (fwd+bwd latency): 34.07 TFLOPS
step latency: 34.12 s
iter latency: 41.39 s
samples/second: 24.74
----------------------------- Aggregated Profile per GPU -----------------------------
Top 1 modules in terms of params, MACs or fwd latency at different model depths:
depth 0:
params - {
'GPT2Model': '1.29 M'}
MACs - {
'GPT2Model': '41271.95 GMACs'}
fwd latency - {
'GPT2Model': '1.84 s'}
depth 1:
params - {
'TransformerLanguageModel': '1.29 M'}
MACs - {
'TransformerLanguageModel': '39584.03 GMACs'}
fwd latency - {
'TransformerLanguageModel': '1.83 s'}
depth 2:
params - {
'ParallelTransformer': '1.29 M'}
MACs - {
'ParallelTransformer': '39584.03 GMACs'}
fwd latency - {
'ParallelTransformer': '1.81 s'}
depth 3:
params - {
'ModuleList': '1.28 M'}
MACs - {
'ModuleList': '39584.03 GMACs'}
fwd latency - {
'ModuleList': '1.3 s'}
depth 4:
params - {
'ParallelTransformerLayerPart2': '688.15 k'}
MACs - {
'ParallelTransformerLayerPart2': '26388.28 GMACs'}
fwd latency - {
'ParallelTransformerLayerPart2': '865.73 ms'}
depth 5:
params - {
'ParallelMLP': '491.54 k'}
MACs - {
'ParallelMLP': '26388.28 GMACs'}
fwd latency - {
'ParallelMLP': '849.4 ms'}
------------------------------ Detailed Profile per GPU ------------------------------
Each module profile is listed after its name in the following order:
params, percentage of total params, MACs, percentage of total MACs, fwd latency, percentage of total fwd latency, fwd FLOPS
Note: 1. A module can have torch.nn.module or torch.nn.functional to compute logits (e.g. CrossEntropyLoss). They are not counted as submodules, thus not to be printed out. However they make up the difference between a parent's MACs(or latency) and the sum of its submodules'.
1. Number of floating-point operations is a theoretical estimation, thus FLOPS computed using that could be larger than the maximum system throughput.
2. The fwd latency listed in the top module's profile is directly captured at the module forward function in PyTorch, thus it's less than the fwd latency shown above which is captured in DeepSpeed.
GPT2Model(
1.29 M, 100.00% Params, 41271.95 GMACs, 100.00% MACs, 1.84 s, 100.00% latency, 44.78 TFLOPS,
(language_model): TransformerLanguageModel(
1.29 M, 100.00% Params, 39584.03 GMACs, 95.91% MACs, 1.83 s, 99.11% latency, 43.34 TFLOPS,
(embedding): Embedding(
2, 0.00% Params, 0 MACs, 0.00% MACs, 18.1 ms, 0.98% latency, 0.0 FLOPS,
(word_embeddings): VocabParallelEmbedding(1, 0.00% Params, 0 MACs, 0.00% MACs, 164.75 us, 0.01% latency, 0.0 FLOPS, )
(position_embeddings): Embedding(1, 0.00% Params, 0 MACs, 0.00% MACs, 489.23 us, 0.03% latency, 0.0 FLOPS, 1024, 8192)
(embedding_dropout): Dropout(0, 0.00% Params, 0 MACs, 0.00% MACs, 93.94 us, 0.01% latency, 0.0 FLOPS, p=0.1, inplace=False)
)
(transformer): ParallelTransformer(
1.29 M, 100.00% Params, 39584.03 GMACs, 95.91% MACs, 1.81 s, 98.11% latency, 43.78 TFLOPS,
(layers): ModuleList(
1.28 M, 98.73% Params, 39584.03 GMACs, 95.91% MACs, 1.3 s, 70.66% latency, 60.79 TFLOPS,
(0): ParallelTransformerLayerPart1(
49.15 k, 3.80% Params, 1099.65 GMACs, 2.66% MACs, 23.5 ms, 1.27% latency, 93.6 TFLOPS,
(input_layernorm): FusedLayerNorm(16.38 k, 1.27% Params, 0 MACs, 0.00% MACs, 128.75 us, 0.01% latency, 0.0 FLOPS, torch.Size([8192]), eps=1e-05, elementwise_affine=True)
(attention): ParallelSelfAttention(
32.77 k, 2.53% Params, 1099.65 GMACs, 2.66% MACs, 22.8 ms, 1.24% latency, 96.46 TFLOPS,
(query_key_value): ColumnParallelLinear(24.58 k, 1.90% Params, 824.63 GMACs, 2.00% MACs, 8.93 ms, 0.48% latency, 184.7 TFLOPS, )
(scale_mask_softmax): FusedScaleMaskSoftmax(0, 0.00% Params, 134.22 MMACs, 0.00% MACs, 151.16 us, 0.01% latency, 1.78 TFLOPS, )
(attention_dropout): Dropout(0, 0.00% Params, 0 MACs, 0.00% MACs, 79.63 us, 0.00% latency, 0.0 FLOPS, p=0.1, inplace=False)
(dense): RowParallelLinear(8.19 k, 0.63% Params, 274.88 GMACs, 0.67% MACs, 2.67 ms, 0.14% latency, 205.81 TFLOPS, )
)
)
(1): ParallelTransformerLayerPart2(
57.35 k, 4.43% Params, 2199.02 GMACs, 5.33% MACs, 77.53 ms, 4.21% latency, 56.73 TFLOPS,
(post_attention_layernorm): FusedLayerNorm(16.38 k, 1.27% Params, 0 MACs, 0.00% MACs, 116.11 us, 0.01% latency, 0.0 FLOPS, torch.Size([8192]), eps=1e-05, elementwise_affine=True)
(mlp): ParallelMLP(
40.96 k, 3.16% Params, 2199.02 GMACs, 5.33% MACs, 76.19 ms, 4.13% latency, 57.72 TFLOPS,
(dense_h_to_4h): ColumnParallelLinear(32.77 k, 2.53% Params, 1099.51 GMACs, 2.66% MACs, 10.79 ms, 0.59% latency, 203.81 TFLOPS, )
(dense_4h_to_h): RowParallelLinear(8.19 k, 0.63% Params, 1099.51 GMACs, 2.66% MACs, 14.38 ms, 0.78% latency, 152.95 TFLOPS, )
)
)
...
(23): ParallelTransformerLayerPart2(...)
)
(final_layernorm): FusedLayerNorm(16.38 k, 1.27% Params, 0 MACs, 0.00% MACs, 110.86 us, 0.01% latency, 0.0 FLOPS, torch.Size([8192]), eps=1e-05, elementwise_affine=True)
)
)
)
------------------------------------------------------------------------------
最新の DeepSpeed-Megatron ウェアハウスを参照し、モデルのトレーニング時に DeepSpeed 構成ファイルを DeepSpeed Profiler に構成できます。
DeepSpeed ランタイム環境外での使用
プロファイラーは、DeepSpeed ランタイム環境の外部でスタンドアロン パッケージとして使用できます。flops_profiler
DeepSpeed をインストールし、パッケージをインポートするだけで API を直接使用できます。DeepSpeedのインストール方法については、DeepSpeedインストールガイドを参照してください。
モデル推論では
トレーニングされたモデルの推論状態をプロファイリングするには、get_model_profile
関数を使用します。いくつかの例を以下に示します。
AlexNet の例
次の例は、DeepSpeed flops プロファイラーを使用して AlexNet をプロファイリングする方法を示しています。
import torchvision.models as models
import torch
from deepspeed.profiling.flops_profiler import get_model_profile
from deepspeed.accelerator import get_accelerator
with get_accelerator().device(0):
model = models.alexnet()
batch_size = 256
flops, macs, params = get_model_profile(model=model, # model
input_shape=(batch_size, 3, 224, 224), # input shape to the model. If specified, the model takes a tensor with this shape as the only positional argument.
args=None, # list of positional arguments to the model.
kwargs=None, # dictionary of keyword arguments to the model.
print_profile=True, # prints the model graph with the measured profile attached to each module
detailed=True, # print the detailed profile
module_depth=-1, # depth into the nested modules, with -1 being the inner most modules
top_modules=1, # the number of top modules to print aggregated profile
warm_up=10, # the number of warm-ups before measuring the time of each module
as_string=True, # print raw numbers (e.g. 1000) or as human-readable strings (e.g. 1k)
output_file=None, # path to the output file. If None, the profiler prints to stdout.
ignore_modules=None) # the list of modules to ignore in the profiling
BERT の例
from functools import partial
import torch
from transformers import BertForSequenceClassification, BertTokenizer
from deepspeed.profiling.flops_profiler import get_model_profile
from deepspeed.accelerator import get_accelerator
def bert_input_constructor(batch_size, seq_len, tokenizer):
fake_seq = ""
for _ in range(seq_len - 2): # ignore the two special tokens [CLS] and [SEP]
fake_seq += tokenizer.pad_token
inputs = tokenizer([fake_seq] * batch_size,
padding=True,
truncation=True,
return_tensors="pt")
labels = torch.tensor([1] * batch_size)
inputs = dict(inputs)
inputs.update({
"labels": labels})
return inputs
with get_accelerator().device(0):
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertForSequenceClassification.from_pretrained('bert-base-uncased')
batch_size = 4
seq_len = 128
enable_profile = True
if enable_profile:
flops, macs, params = get_model_profile(
model,
kwargs=bert_input_constructor(batch_size, seq_len, tokenizer),
print_profile=True,
detailed=True,
)
else:
inputs = bert_input_constructor((batch_size, seq_len), tokenizer)
outputs = model(inputs)
モデルトレーニングワークフロー内
トレーニング ワークフローでモデルのフォワード パスをプロファイリングするには、FlopsProfiler
クラスを使用します。FlopsProfiler
このクラスは次のメソッドを提供します。
start_profile()
- プロファイリングを開始します。get_total_flops(as_string=False)
- モデル内の浮動小数点演算の合計数を返します。get_total_macs(as_string=False
- モデル内の Mac の合計数を返します。get_total_params(as_string=False)
- モデル内のパラメータの合計数を返します。print_model_profile(profile_step=1, module_depth=-1, top_modules=3, detailed=True, output_file=None)
- モデルプロファイルを印刷します。stop_profile()
- プロファイリングを停止します。これにより、モデル内の浮動小数点演算のカウントが停止されます。end_profile()
- そうじする。これにより、プロファイリング中にモデルに追加されたプロファイリング属性がクリーンアップされます。これは、プロファイリングの最後で、 を呼び出した後get_total_flops
、get_total_params
またはprint_model_profile
その後に実行する必要があります。
トレーニングワークフローの例
以下は、一般的なトレーニング ワークフローでこのメソッドを使用する例です。
from deepspeed.profiling.flops_profiler import FlopsProfiler
model = Model()
prof = FlopsProfiler(model)
profile_step = 5
print_profile= True
for step, batch in enumerate(data_loader):
# start profiling at training step "profile_step"
if step == profile_step:
prof.start_profile()
# forward() method
loss = model(batch)
# end profiling and print output
if step == profile_step: # if using multi nodes, check global_rank == 0 as well
prof.stop_profile()
flops = prof.get_total_flops()
macs = prof.get_total_macs()
params = prof.get_total_params()
if print_profile:
prof.print_model_profile(profile_step=profile_step)
prof.end_profile()
# runs backpropagation
loss.backward()
# weight update
optimizer.step()