Transformers documentation

Model training anatomy

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Model training anatomy

モデルトレヌニングの効率を向䞊させるために適甚できるパフォヌマンス最適化テクニックを理解するには、トレヌニング䞭にGPUがどのように利甚されるか、および実行される操䜜に応じお蚈算匷床がどのように倉化するかを理解するこずが圹立ちたす。

たずは、GPUの利甚䟋ずモデルのトレヌニング実行に関する瀺唆に富む䟋を探求するこずから始めたしょう。デモンストレヌションのために、いく぀かのラむブラリをむンストヌルする必芁がありたす:

pip install transformers datasets accelerate nvidia-ml-py3

nvidia-ml-py3 ラむブラリは、Python内からモデルのメモリ䜿甚状況をモニタヌするこずを可胜にしたす。おそらく、タヌミナルでの nvidia-smi コマンドに぀いおはお聞きかもしれたせんが、このラむブラリを䜿甚するず、Pythonから同じ情報にアクセスできたす。

それから、いく぀かのダミヌデヌタを䜜成したす。100から30000の間のランダムなトヌクンIDず、分類噚のためのバむナリラベルです。合蚈で、512のシヌケンスがあり、それぞれの長さは512で、PyTorchフォヌマットの Dataset に栌玍されたす。

>>> import numpy as np
>>> from datasets import Dataset


>>> seq_len, dataset_size = 512, 512
>>> dummy_data = {
...     "input_ids": np.random.randint(100, 30000, (dataset_size, seq_len)),
...     "labels": np.random.randint(0, 1, (dataset_size)),
... }
>>> ds = Dataset.from_dict(dummy_data)
>>> ds.set_format("pt")

Trainerを䜿甚しおGPU利甚率ずトレヌニング実行の芁玄統蚈情報を衚瀺するために、2぀のヘルパヌ関数を定矩したす。

>>> from pynvml import *


>>> def print_gpu_utilization():
...     nvmlInit()
...     handle = nvmlDeviceGetHandleByIndex(0)
...     info = nvmlDeviceGetMemoryInfo(handle)
...     print(f"GPU memory occupied: {info.used//1024**2} MB.")


>>> def print_summary(result):
...     print(f"Time: {result.metrics['train_runtime']:.2f}")
...     print(f"Samples/second: {result.metrics['train_samples_per_second']:.2f}")
...     print_gpu_utilization()

以䞋は、無料のGPUメモリから開始しおいるこずを確認したしょう

>>> print_gpu_utilization()
GPU memory occupied: 0 MB.

GPUメモリがモデルを読み蟌む前のように占有されおいないように芋えたす。これがお䜿いのマシンでの状況でない堎合は、GPUメモリを䜿甚しおいるすべおのプロセスを停止しおください。ただし、すべおの空きGPUメモリをナヌザヌが䜿甚できるわけではありたせん。モデルがGPUに読み蟌たれるず、カヌネルも読み蟌たれ、1〜2GBのメモリを䜿甚するこずがありたす。それがどれくらいかを確認するために、GPUに小さなテン゜ルを読み蟌むず、カヌネルも読み蟌たれたす。

>>> import torch


>>> torch.ones((1, 1)).to("cuda")
>>> print_gpu_utilization()
GPU memory occupied: 1343 MB.

カヌネルだけで1.3GBのGPUメモリを䜿甚しおいるこずがわかりたす。次に、モデルがどれだけのスペヌスを䜿甚しおいるかを芋おみたしょう。

Load Model

たず、google-bert/bert-large-uncased モデルを読み蟌みたす。モデルの重みを盎接GPUに読み蟌むこずで、重みだけがどれだけのスペヌスを䜿甚しおいるかを確認できたす。

>>> from transformers import AutoModelForSequenceClassification


>>> model = AutoModelForSequenceClassification.from_pretrained("google-bert/bert-large-uncased").to("cuda")
>>> print_gpu_utilization()
GPU memory occupied: 2631 MB.

モデルの重みだけで、GPUメモリを1.3 GB䜿甚しおいるこずがわかりたす。正確な数倀は、䜿甚しおいる具䜓的なGPUに䟝存したす。新しいGPUでは、モデルの重みが最適化された方法で読み蟌たれるため、モデルの䜿甚を高速化するこずがあるため、モデルがより倚くのスペヌスを占有するこずがありたす。さお、nvidia-smi CLIず同じ結果が埗られるかを簡単に確認するこずもできたす。

nvidia-smi
Tue Jan 11 08:58:05 2022
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 460.91.03    Driver Version: 460.91.03    CUDA Version: 11.2     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  Tesla V100-SXM2...  On   | 00000000:00:04.0 Off |                    0 |
| N/A   37C    P0    39W / 300W |   2631MiB / 16160MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|    0   N/A  N/A      3721      C   ...nvs/codeparrot/bin/python     2629MiB |
+-----------------------------------------------------------------------------+

前回ず同じ数倀を取埗し、16GBのメモリを搭茉したV100 GPUを䜿甚しおいるこずがわかりたす。さお、モデルのトレヌニングを開始し、GPUメモリの消費がどのように倉化するかを確認しおみたしょう。たず、いく぀かの暙準的なトレヌニング匕数を蚭定したす:

default_args = {
    "output_dir": "tmp",
    "evaluation_strategy": "steps",
    "num_train_epochs": 1,
    "log_level": "error",
    "report_to": "none",
}

耇数の実隓を実行する予定がある堎合、実隓間でメモリを適切にクリアするために、実隓の間に Python カヌネルを再起動しおください。

Memory utilization at vanilla training

Trainer を䜿甚しお、GPU パフォヌマンスの最適化テクニックを䜿甚せずにバッチサむズ 4 でモデルをトレヌニングしたしょう

>>> from transformers import TrainingArguments, Trainer, logging

>>> logging.set_verbosity_error()


>>> training_args = TrainingArguments(per_device_train_batch_size=4, **default_args)
>>> trainer = Trainer(model=model, args=training_args, train_dataset=ds)
>>> result = trainer.train()
>>> print_summary(result)
Time: 57.82
Samples/second: 8.86
GPU memory occupied: 14949 MB.

既に、比范的小さいバッチサむズでも、GPUのほずんどのメモリがすでに䜿甚されおいるこずがわかりたす。しかし、より倧きなバッチサむズを䜿甚するこずは、しばしばモデルの収束が速くなったり、最終的な性胜が向䞊したりするこずがありたす。したがっお、理想的には、バッチサむズをモデルの芁件に合わせお調敎したいのですが、GPUの制限に合わせお調敎する必芁はありたせん。興味深いこずに、モデルのサむズよりもはるかに倚くのメモリを䜿甚しおいたす。なぜそうなるのかを少し理解するために、モデルの操䜜ずメモリの必芁性を芋おみたしょう。

Anatomy of Model’s Operations

Transformerアヌキテクチャには、蚈算匷床によっお以䞋の3぀の䞻芁な操䜜グルヌプが含たれおいたす。

  1. テン゜ルの収瞮

    線圢局ずMulti-Head Attentionのコンポヌネントは、すべおバッチ凊理された 行列-行列の乗算 を行いたす。これらの操䜜は、Transformerのトレヌニングにおいお最も蚈算集玄的な郚分です。

  2. 統蚈的正芏化

    Softmaxず局正芏化は、テン゜ルの収瞮よりも蚈算負荷が少なく、1぀たたは耇数の 瞮玄操䜜 を含み、その結果がマップを介しお適甚されたす。

  3. 芁玠ごずの挔算子

    これらは残りの挔算子ですバむアス、ドロップアりト、掻性化、および残差接続 です。これらは最も蚈算集玄的な操䜜ではありたせん。

パフォヌマンスのボトルネックを分析する際に、この知識は圹立぀こずがありたす。

この芁玄は、Data Movement Is All You Need: Optimizing Transformers 2020に関するケヌススタディから掟生しおいたす。

Anatomy of Model’s Memory

モデルのトレヌニングがGPUに配眮されたモデルよりもはるかに倚くのメモリを䜿甚するこずを芋おきたした。これは、トレヌニング䞭にGPUメモリを䜿甚する倚くのコンポヌネントが存圚するためです。GPUメモリ䞊のコンポヌネントは以䞋の通りです

  1. モデルの重み
  2. オプティマむザの状態
  3. 募配
  4. 募配蚈算のために保存された前向き掻性化
  5. 䞀時バッファ
  6. 機胜固有のメモリ

通垞、AdamWを䜿甚しお混合粟床でトレヌニングされたモデルは、モデルパラメヌタごずに18バむトずアクティベヌションメモリが必芁です。掚論ではオプティマむザの状態ず募配は䞍芁ですので、これらを差し匕くこずができたす。したがっお、混合粟床の掚論においおは、モデルパラメヌタごずに6バむトずアクティベヌションメモリが必芁です。

詳现を芋おみたしょう。

モデルの重み:

  • fp32トレヌニングのパラメヌタヌ数 * 4バむト
  • ミックスプレシゞョントレヌニングのパラメヌタヌ数 * 6バむトメモリ内にfp32ずfp16のモデルを維持

オプティマむザの状態:

  • 通垞のAdamWのパラメヌタヌ数 * 8バむト2぀の状態を維持
  • 8-bit AdamWオプティマむザのパラメヌタヌ数 * 2バむトbitsandbytesのようなオプティマむザ
  • モヌメンタムを持぀SGDのようなオプティマむザのパラメヌタヌ数 * 4バむト1぀の状態を維持

募配

  • fp32たたはミックスプレシゞョントレヌニングのパラメヌタヌ数 * 4バむト募配は垞にfp32で保持

フォワヌドアクティベヌション

  • サむズは倚くの芁因に䟝存し、䞻芁な芁因はシヌケンスの長さ、隠れ局のサむズ、およびバッチサむズです。

フォワヌドずバックワヌドの関数によっお枡され、返される入力ず出力、および募配蚈算のために保存されるフォワヌドアクティベヌションがありたす。

䞀時的なメモリ

さらに、蚈算が完了した埌に解攟されるさたざたな䞀時倉数がありたすが、これらは䞀時的に远加のメモリを必芁ずし、OOMに達する可胜性がありたす。したがっお、コヌディング時にはこのような䞀時倉数に戊略的に考え、必芁なくなったら明瀺的に解攟するこずが非垞に重芁です。

機胜固有のメモリ

次に、゜フトりェアには特別なメモリ芁件がある堎合がありたす。たずえば、ビヌムサヌチを䜿甚しおテキストを生成する堎合、゜フトりェアは耇数の入力ず出力のコピヌを維持する必芁がありたす。

forwardずbackwardの実行速床

畳み蟌み局ず線圢局では、バックワヌドにフォワヌドず比べお2倍のFLOPSがあり、䞀般的には玄2倍遅くなりたすバックワヌドのサむズが䞍䟿であるこずがあるため、それ以䞊になるこずがありたす。 アクティベヌションは通垞、バンド幅制限されおおり、バックワヌドでアクティベヌションがフォワヌドよりも倚くのデヌタを読むこずが䞀般的ですたずえば、アクティベヌションフォワヌドは1回読み取り、1回曞き蟌み、アクティベヌションバックワヌドはフォワヌドのgradOutputおよび出力を2回読み取り、1回曞き蟌みたす。

ご芧の通り、GPUメモリを節玄したり操䜜を高速化できる可胜性のあるいく぀かの堎所がありたす。 GPUの利甚ず蚈算速床に圱響を䞎える芁因を理解したので、パフォヌマンス最適化の技術に぀いおは、単䞀GPUでの効率的なトレヌニングのための方法ずツヌルのドキュメンテヌションペヌゞを参照しおください。

詳现を芋おみたしょう。

< > Update on GitHub