-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtrain_model_parallel.py
More file actions
113 lines (80 loc) · 2.87 KB
/
Copy pathtrain_model_parallel.py
File metadata and controls
113 lines (80 loc) · 2.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import time
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from src.data import RandomTextDataset
from src.runtime import require_cuda
MAX_STEPS = 100
class ManualModelParallelTransformer(nn.Module):
def __init__(
self,
vocab_size: int = 32000,
seq_len: int = 256,
d_model: int = 512,
nhead: int = 8,
num_classes: int = 10,
dim_feedforward: int = 2048,
):
super().__init__()
self.gpu0 = torch.device("cuda:0")
self.gpu1 = torch.device("cuda:1")
self.gpu2 = torch.device("cuda:2")
self.seq_len = seq_len
self.token_emb = nn.Embedding(vocab_size, d_model).to(self.gpu0)
self.pos_emb = nn.Embedding(seq_len, d_model).to(self.gpu0)
def make_layer():
return nn.TransformerEncoderLayer(
d_model=d_model,
nhead=nhead,
dim_feedforward=dim_feedforward,
batch_first=True,
activation="gelu",
)
self.block0 = nn.Sequential(make_layer(), make_layer()).to(self.gpu0)
self.block1 = nn.Sequential(make_layer(), make_layer()).to(self.gpu1)
self.block2 = nn.Sequential(make_layer(), make_layer()).to(self.gpu2)
self.norm = nn.LayerNorm(d_model).to(self.gpu2)
self.head = nn.Linear(d_model, num_classes).to(self.gpu2)
def forward(self, input_ids):
batch_size, seq_len = input_ids.shape
positions = torch.arange(seq_len, device=self.gpu0)
positions = positions.unsqueeze(0).expand(batch_size, seq_len)
x = self.token_emb(input_ids) + self.pos_emb(positions)
x = self.block0(x)
x = x.to(self.gpu1)
x = self.block1(x)
x = x.to(self.gpu2)
x = self.block2(x)
x = self.norm(x[:, 0])
logits = self.head(x)
return logits
def main():
require_cuda(min_devices=3)
dataset = RandomTextDataset(num_samples=5000)
loader = DataLoader(
dataset,
batch_size=64,
shuffle=True,
num_workers=4,
pin_memory=True,
)
model = ManualModelParallelTransformer()
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-4)
criterion = nn.CrossEntropyLoss().to("cuda:2")
model.train()
start = time.time()
for step, (input_ids, labels) in enumerate(loader):
if step >= MAX_STEPS:
break
input_ids = input_ids.to("cuda:0", non_blocking=True)
labels = labels.to("cuda:2", non_blocking=True)
optimizer.zero_grad(set_to_none=True)
logits = model(input_ids)
loss = criterion(logits, labels)
loss.backward()
optimizer.step()
if step % 20 == 0:
elapsed = time.time() - start
print(f"step={step}, loss={loss.item():.4f}, elapsed={elapsed:.2f}s")
if __name__ == "__main__":
main()