モデルを複数GPUに分割 - Shinichi0713/LLM-fundamental-study GitHub Wiki
はい、PyTorchでモデルを複数GPUに分割して並列計算することは可能です。ただし、
「分割」にはいくつかの方法・意味合いがありますので、代表的な手法とその特徴を説明します。
1. Data Parallel(データ並列)
- モデル全体を各GPUに「複製」し、異なるデータを並列で処理します。
- 代表例:
nn.DataParallel
やnn.DistributedDataParallel
- 1つのGPUにモデル全体が入る必要がある(巨大なモデルには不向き)
2. Model Parallel(モデル並列)
- モデルの一部をGPU0、残りをGPU1…のように「分割」して配置します。
- 例えば、前半の層をGPU0、後半をGPU1で計算することで、1枚のGPUに収まらない巨大なモデルも扱えます。
シンプルな例
import torch
import torch.nn as nn
class ModelParallelNet(nn.Module):
def __init__(self):
super().__init__()
self.seq1 = nn.Sequential(nn.Linear(1000, 1000), nn.ReLU())
self.seq2 = nn.Sequential(nn.Linear(1000, 1000), nn.ReLU())
# seq1をcuda:0、seq2をcuda:1に配置
self.seq1.to('cuda:0')
self.seq2.to('cuda:1')
def forward(self, x):
x = x.to('cuda:0')
x = self.seq1(x)
x = x.to('cuda:1')
x = self.seq2(x)
return x
- forward内で明示的にデバイスを移動させる必要があります。
- モデルの構造によっては通信コストが増えるため、分割位置の設計が重要です。
3. Pipeline Parallel(パイプライン並列)
- モデルを複数の「ステージ」に分割し、各ステージを異なるGPUに割り当ててパイプライン処理します。
- PyTorchの
torch.distributed.pipeline.sync.Pipe
などで実装可能です。
例(Pipe API)
from torch.distributed.pipeline.sync import Pipe
model = nn.Sequential(
nn.Linear(1000, 1000),
nn.ReLU(),
nn.Linear(1000, 1000),
nn.ReLU()
)
# 2分割してcuda:0, cuda:1に割り当て
model = Pipe(model, devices=['cuda:0', 'cuda:1'], chunks=8)
4. まとめ
- モデルの分割(Model Parallel, Pipeline Parallel)は可能
- 明示的に
.to('cuda:0')
や.to('cuda:1')
で層ごとに割り当てる - 通信コストや実装の複雑さに注意
- 一般的にはDataParallel/DDP、モデルが巨大な場合はModel/Pipeline Parallelを使う
参考
ご質問の「モデルを複数GPUに分割」は可能です。
用途・モデルサイズ・実装難易度に応じて最適な手法を選択してください。