📖

Deep Speedについてまとめ

2023/12/19に公開

概要

https://www.deepspeed.ai/getting-started/
Deep Speedについて学習した際のまとめです。

Getting Started

https://www.deepspeed.ai/getting-started/

initialize

初期化処理

model_engine, optimizer, _, _ = deepspeed.initialize(args=cmd_args,
                                                     model=model,
                                                     model_parameters=params)

NCCL backend

Deep Speedでは基本的にNCCL backendを使い分散処理を行う。

訓練のコード

訓練コードは以下の様になる。

for step, batch in enumerate(data_loader):
    #forward() method
    loss = model_engine(batch)

    #runs backpropagation
    model_engine.backward(loss)

    #weight update
    model_engine.step()

学習率スケジューラーによって、並列学習、混合精度訓練を自動で行ってくれる。

DeepSpeed Configuration

設定ファイル。

{
  "train_batch_size": 8,
  "gradient_accumulation_steps": 1,
  "optimizer": {
    "type": "Adam",
    "params": {
      "lr": 0.00015
    }
  },
  "fp16": {
    "enabled": true
  },
  "zero_optimization": true
}

hostfile

マルチノードで実行する際のノード一覧を記載。

worker-1 slots=4
worker-2 slots=4

ノードに存在するGPU数も記載する。

起動コマンド

deepspeed --hostfile=myhostfile <client_entry.py> <client args> \
  --deepspeed --deepspeed_config ds_config.json

Getting Started with DeepSpeed for Inferencing Transformer based Models

https://www.deepspeed.ai/tutorials/inference-tutorial/

互換性のあるモデル

https://github.com/microsoft/DeepSpeed/blob/master/deepspeed/module_inject/replace_policy.py

こちらに定義されているモデルのみ互換性がある。(推論のみの話?)

推論コード

# create the model
if args.pre_load_checkpoint:
    model = model_class.from_pretrained(args.model_name_or_path)
else:
    model = model_class()
...

import deepspeed

# Initialize the DeepSpeed-Inference engine
ds_engine = deepspeed.init_inference(model,
                                 mp_size=2,
                                 dtype=torch.half,
                                 checkpoint=None if args.pre_load_checkpoint else args.checkpoint_json,
                                 replace_with_kernel_inject=True)
model = ds_engine.module
output = model('Input String')

互換性のないモデルで並列に推論したいケース

injection_policyを指定すれば互換性がなくてもできる?

# create the model
import transformers
from transformers.models.t5.modeling_t5 import T5Block

import deepspeed

pipe = pipeline("text2text-generation", model="google/t5-v1_1-small", device=local_rank)
# Initialize the DeepSpeed-Inference engine
pipe.model = deepspeed.init_inference(
    pipe.model,
    mp_size=world_size,
    dtype=torch.float,
    injection_policy={T5Block: ('SelfAttention.o', 'EncDecAttention.o', 'DenseReluDense.wo')}
)
output = pipe('Input String')

実行。

deepspeed --num_gpus 2 inference.py

GPT NEO 2.7Bで推論するサンプル

# Filename: gpt-neo-2.7b-generation.py
import os
import deepspeed
import torch
from transformers import pipeline

local_rank = int(os.getenv('LOCAL_RANK', '0'))
world_size = int(os.getenv('WORLD_SIZE', '1'))
generator = pipeline('text-generation', model='EleutherAI/gpt-neo-2.7B',
                     device=local_rank)



generator.model = deepspeed.init_inference(generator.model,
                                           mp_size=world_size,
                                           dtype=torch.float,
                                           replace_with_kernel_inject=True)

string = generator("DeepSpeed is", do_sample=True, min_length=50)
if not torch.distributed.is_initialized() or torch.distributed.get_rank() == 0:
    print(string)

実行

deepspeed --num_gpus 2 gpt-neo-2.7b-generation.py

量子化

以下の様に指定する。

import deepspeed
model = deepspeed.init_inference(model,
                                 checkpoint='./checkpoint.json',
                                 dtype=torch.int8,
                                 quantization_setting=(quantize_groups,
                                                       mlp_extra_grouping)
                                )

Training your large model with DeepSpeed

https://www.deepspeed.ai/tutorials/large-models-w-deepspeed/

Overview

DeepSpeedは巨大なモデルでのトレーニングを可能にするための技術をまとめたもの。

巨大なモデルを訓練するための2つの方法

ZeRO based technologies

並列でGPUを動作させた時のメモリの効率化、ZeRO-Offload and ZeRO-Infinityという技術も使うことができる。

3D Parallelism based technologies

テンソルスライシング、パイプライン並列、データ並列(またはZeROによるデータ並列)という3つの異なる並列技術の組み合わせ。
使用するにはモデルのコードのリファクタリングが必要になってくる。

どの技術を使うか

3D Parallelism based technologiesを使うケース

GPT-2またはGPT-3系のモデルの場合は3D Parallelismへの対応がすでに終わっている可能性が高いのでこちらを使用すると良い。

詳細は以下を参照
https://www.deepspeed.ai/tutorials/pipeline/
https://www.microsoft.com/en-us/research/blog/deepspeed-extreme-scale-model-training-for-everyone/

ZeRO based technologiesを使うケース

3D Parallelismへの対応がされていないモデルの場合はこちらを使うのが良い。
リファクタリングを必要としないため。
この方法でうまくいったら3D parallelism対応のコード変更を行ってみるのも良い。

ZeRO-OffloadとZeRO-Infinityにもアクセスできるようになる。
ZeROについての詳細は以下を参照。

https://www.deepspeed.ai/tutorials/zero/

パフォーマンスとのトレードオフ

GPUあたりのバッチサイズが極端に小さくない場合、ZeROと3D並列の性能は概ね同等。
データ並列処理自体の通信コストとほとんど変わらない。

何千ものGPUでトレーニングする場合かつバッチサイズが小さい場合はZeROだけでは十分な性能を維持できない可能性がある。

そういう場合はバッチサイズを大きくするか3D parallelismにするのが良い。

Discussion