mirror of https://github.com/hpcaitech/ColossalAI
set benchmarks as a git submodule (#156)
* remove benchmark folder * added benchmark submodule * update .gitmodulespull/159/head
parent
f3802d6b06
commit
c7b8ece736
|
@ -0,0 +1,4 @@
|
|||
[submodule "benchmark"]
|
||||
path = benchmark
|
||||
url = https://github.com/hpcaitech/ColossalAI-Benchmark.git
|
||||
branch = main
|
|
@ -0,0 +1 @@
|
|||
Subproject commit c319bc2ee9db32aba4a522eccdf89e8d0fb8d9f0
|
|
@ -1,66 +0,0 @@
|
|||
# Benchmark for Tuning Accuracy and Efficiency
|
||||
|
||||
## Overview
|
||||
|
||||
The benchmark includes our efforts in using Colossal-AI to train different tasks to achieve SOTA results.
|
||||
We are interested in both validataion accuracy and training speed, and prefer larger batch size to take advantage of more GPU devices.
|
||||
For example, we trained vision transformer with batch size 512 on CIFAR10 and 4096 on ImageNet1k, which are basically not used in existing works.
|
||||
Some of the results in the benchmark trained with 8x A100 are shown below.
|
||||
|
||||
| Task | Model | Training Time | Top-1 Accuracy |
|
||||
| ---------- | ------------ | ------------- | -------------- |
|
||||
| CIFAR10 | [ViT-Lite-7/4](https://arxiv.org/pdf/2104.05704.pdf) | ~ 16 min | ~ 90.5% |
|
||||
| ImageNet1k | ViT-S/16 | ~ 16.5 h | ~ 74.5% |
|
||||
|
||||
The `train.py` script in each task runs training with the specific configuration script in `configs/` for different parallelisms.
|
||||
Supported parallelisms include data parallel only (ends with `vanilla`), 1D (ends with `1d`), 2D (ends with `2d`), 2.5D (ends with `2p5d`), 3D (ends with `3d`).
|
||||
|
||||
Each configuration scripts basically includes the following elements, taking ImageNet1k task as example:
|
||||
```
|
||||
TOTAL_BATCH_SIZE = 4096
|
||||
LEARNING_RATE = 3e-3
|
||||
WEIGHT_DECAY = 0.3
|
||||
|
||||
NUM_EPOCHS = 300
|
||||
WARMUP_EPOCHS = 32
|
||||
|
||||
# data parallel only
|
||||
TENSOR_PARALLEL_SIZE = 1
|
||||
TENSOR_PARALLEL_MODE = None
|
||||
|
||||
# parallelism setting
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE),
|
||||
)
|
||||
|
||||
fp16 = dict(mode=AMP_TYPE.TORCH, ) # amp setting
|
||||
|
||||
gradient_accumulation = 2 # accumulate 2 steps for gradient update
|
||||
|
||||
BATCH_SIZE = TOTAL_BATCH_SIZE // gradient_accumulation # actual batch size for dataloader
|
||||
|
||||
clip_grad_norm = 1.0 # clip gradient with norm 1.0
|
||||
```
|
||||
Upper case elements are basically what `train.py` needs, and lower case elements are what Colossal-AI needs to initialize the training.
|
||||
|
||||
## Usage
|
||||
|
||||
To start training, use the following command to run each worker:
|
||||
```
|
||||
$ DATA=/path/to/dataset python train.py --world_size=WORLD_SIZE \
|
||||
--rank=RANK \
|
||||
--local_rank=LOCAL_RANK \
|
||||
--host=MASTER_IP_ADDRESS \
|
||||
--port=MASTER_PORT \
|
||||
--config=CONFIG_FILE
|
||||
```
|
||||
It is also recommended to start training with `torchrun` as:
|
||||
```
|
||||
$ DATA=/path/to/dataset torchrun --nproc_per_node=NUM_GPUS_PER_NODE \
|
||||
--nnodes=NUM_NODES \
|
||||
--node_rank=NODE_RANK \
|
||||
--master_addr=MASTER_IP_ADDRESS \
|
||||
--master_port=MASTER_PORT \
|
||||
train.py --config=CONFIG_FILE
|
||||
```
|
|
@ -1,18 +0,0 @@
|
|||
BATCH_SIZE = 512
|
||||
LEARNING_RATE = 2e-3
|
||||
WEIGHT_DECAY = 3e-2
|
||||
|
||||
TENSOR_PARALLEL_SIZE = 2
|
||||
TENSOR_PARALLEL_MODE = '1d'
|
||||
|
||||
NUM_EPOCHS = 200
|
||||
WARMUP_EPOCHS = 40
|
||||
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE),
|
||||
)
|
||||
|
||||
seed = 42
|
||||
|
||||
LOG_PATH = f"./vit_{TENSOR_PARALLEL_MODE}_cifar10_tp{TENSOR_PARALLEL_SIZE}_bs{BATCH_SIZE}_lr{LEARNING_RATE}/"
|
|
@ -1,18 +0,0 @@
|
|||
BATCH_SIZE = 512
|
||||
LEARNING_RATE = 2e-3
|
||||
WEIGHT_DECAY = 3e-2
|
||||
|
||||
TENSOR_PARALLEL_SIZE = 4
|
||||
TENSOR_PARALLEL_MODE = '2d'
|
||||
|
||||
NUM_EPOCHS = 200
|
||||
WARMUP_EPOCHS = 40
|
||||
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE),
|
||||
)
|
||||
|
||||
seed = 42
|
||||
|
||||
LOG_PATH = f"./vit_{TENSOR_PARALLEL_MODE}_cifar10_tp{TENSOR_PARALLEL_SIZE}_bs{BATCH_SIZE}_lr{LEARNING_RATE}/"
|
|
@ -1,19 +0,0 @@
|
|||
BATCH_SIZE = 512
|
||||
LEARNING_RATE = 2e-3
|
||||
WEIGHT_DECAY = 3e-2
|
||||
|
||||
TENSOR_PARALLEL_SIZE = 4
|
||||
DEPTH = 1
|
||||
TENSOR_PARALLEL_MODE = '2.5d'
|
||||
|
||||
NUM_EPOCHS = 200
|
||||
WARMUP_EPOCHS = 40
|
||||
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE, depth=DEPTH),
|
||||
)
|
||||
|
||||
seed = 42
|
||||
|
||||
LOG_PATH = f"./vit_{TENSOR_PARALLEL_MODE}_cifar10_tp{TENSOR_PARALLEL_SIZE}_bs{BATCH_SIZE}_lr{LEARNING_RATE}/"
|
|
@ -1,18 +0,0 @@
|
|||
BATCH_SIZE = 512
|
||||
LEARNING_RATE = 2e-3
|
||||
WEIGHT_DECAY = 3e-2
|
||||
|
||||
TENSOR_PARALLEL_SIZE = 8
|
||||
TENSOR_PARALLEL_MODE = '3d'
|
||||
|
||||
NUM_EPOCHS = 200
|
||||
WARMUP_EPOCHS = 40
|
||||
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE),
|
||||
)
|
||||
|
||||
seed = 42
|
||||
|
||||
LOG_PATH = f"./vit_{TENSOR_PARALLEL_MODE}_cifar10_tp{TENSOR_PARALLEL_SIZE}_bs{BATCH_SIZE}_lr{LEARNING_RATE}/"
|
|
@ -1,18 +0,0 @@
|
|||
BATCH_SIZE = 512
|
||||
LEARNING_RATE = 2e-3
|
||||
WEIGHT_DECAY = 3e-2
|
||||
|
||||
TENSOR_PARALLEL_SIZE = 1
|
||||
TENSOR_PARALLEL_MODE = None
|
||||
|
||||
NUM_EPOCHS = 200
|
||||
WARMUP_EPOCHS = 40
|
||||
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE),
|
||||
)
|
||||
|
||||
seed = 42
|
||||
|
||||
LOG_PATH = f"./vit_{TENSOR_PARALLEL_MODE}_cifar10_tp{TENSOR_PARALLEL_SIZE}_bs{BATCH_SIZE}_lr{LEARNING_RATE}/"
|
|
@ -1,119 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
import os
|
||||
|
||||
import colossalai
|
||||
import torch
|
||||
import torchvision
|
||||
from colossalai.builder import *
|
||||
from colossalai.core import global_context as gpc
|
||||
from colossalai.logging import get_dist_logger
|
||||
from colossalai.nn import Accuracy, CrossEntropyLoss
|
||||
from colossalai.nn.lr_scheduler import CosineAnnealingWarmupLR
|
||||
from colossalai.trainer import Trainer, hooks
|
||||
from colossalai.utils import MultiTimer, get_dataloader
|
||||
from model_zoo.vit import vit_lite_depth7_patch4_32
|
||||
from torchvision import transforms
|
||||
|
||||
DATASET_PATH = str(os.environ['DATA'])
|
||||
|
||||
|
||||
def build_cifar(batch_size):
|
||||
transform_train = transforms.Compose([
|
||||
transforms.RandomCrop(32, padding=4),
|
||||
transforms.AutoAugment(policy=transforms.AutoAugmentPolicy.CIFAR10),
|
||||
transforms.ToTensor(),
|
||||
transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
|
||||
])
|
||||
transform_test = transforms.Compose([
|
||||
transforms.Resize(32),
|
||||
transforms.ToTensor(),
|
||||
transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
|
||||
])
|
||||
|
||||
train_dataset = torchvision.datasets.CIFAR10(root=DATASET_PATH,
|
||||
train=True,
|
||||
download=True,
|
||||
transform=transform_train)
|
||||
test_dataset = torchvision.datasets.CIFAR10(root=DATASET_PATH, train=False, transform=transform_test)
|
||||
train_dataloader = get_dataloader(dataset=train_dataset,
|
||||
shuffle=True,
|
||||
batch_size=batch_size,
|
||||
num_workers=4,
|
||||
pin_memory=True)
|
||||
test_dataloader = get_dataloader(dataset=test_dataset, batch_size=batch_size, num_workers=4, pin_memory=True)
|
||||
return train_dataloader, test_dataloader
|
||||
|
||||
|
||||
def train_cifar():
|
||||
args = colossalai.get_default_parser().parse_args()
|
||||
# standard launch
|
||||
# colossalai.launch(config=args.config,
|
||||
# rank=args.rank,
|
||||
# world_size=args.world_size,
|
||||
# local_rank=args.local_rank,
|
||||
# host=args.host,
|
||||
# port=args.port)
|
||||
|
||||
# launch from torchrun
|
||||
colossalai.launch_from_torch(config=args.config)
|
||||
|
||||
logger = get_dist_logger()
|
||||
if hasattr(gpc.config, 'LOG_PATH'):
|
||||
if gpc.get_global_rank() == 0:
|
||||
log_path = gpc.config.LOG_PATH
|
||||
if not os.path.exists(log_path):
|
||||
os.mkdir(log_path)
|
||||
logger.log_to_file(log_path)
|
||||
|
||||
model = vit_lite_depth7_patch4_32()
|
||||
|
||||
train_dataloader, test_dataloader = build_cifar(gpc.config.BATCH_SIZE // gpc.data_parallel_size)
|
||||
|
||||
criterion = CrossEntropyLoss(label_smoothing=0.1)
|
||||
|
||||
optimizer = torch.optim.AdamW(model.parameters(), lr=gpc.config.LEARNING_RATE, weight_decay=gpc.config.WEIGHT_DECAY)
|
||||
|
||||
steps_per_epoch = len(train_dataloader)
|
||||
|
||||
lr_scheduler = CosineAnnealingWarmupLR(optimizer=optimizer,
|
||||
total_steps=gpc.config.NUM_EPOCHS * steps_per_epoch,
|
||||
warmup_steps=gpc.config.WARMUP_EPOCHS * steps_per_epoch)
|
||||
|
||||
engine, train_dataloader, test_dataloader, lr_scheduler = colossalai.initialize(model=model,
|
||||
optimizer=optimizer,
|
||||
criterion=criterion,
|
||||
train_dataloader=train_dataloader,
|
||||
test_dataloader=test_dataloader,
|
||||
lr_scheduler=lr_scheduler)
|
||||
|
||||
logger.info("Engine is built", ranks=[0])
|
||||
|
||||
timer = MultiTimer()
|
||||
|
||||
trainer = Trainer(engine=engine, logger=logger, timer=timer)
|
||||
logger.info("Trainer is built", ranks=[0])
|
||||
|
||||
hook_list = [
|
||||
hooks.LogMetricByEpochHook(logger=logger),
|
||||
hooks.LogMetricByStepHook(),
|
||||
# hooks.LogTimingByEpochHook(timer=timer, logger=logger),
|
||||
# hooks.LogMemoryByEpochHook(logger=logger),
|
||||
hooks.AccuracyHook(accuracy_func=Accuracy()),
|
||||
hooks.LossHook(),
|
||||
hooks.ThroughputHook(),
|
||||
hooks.LRSchedulerHook(lr_scheduler=lr_scheduler, by_epoch=False)
|
||||
]
|
||||
|
||||
logger.info("Train start", ranks=[0])
|
||||
trainer.fit(train_dataloader=train_dataloader,
|
||||
test_dataloader=test_dataloader,
|
||||
epochs=gpc.config.NUM_EPOCHS,
|
||||
hooks=hook_list,
|
||||
display_progress=True,
|
||||
test_interval=1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
train_cifar()
|
|
@ -1,29 +0,0 @@
|
|||
from colossalai.amp import AMP_TYPE
|
||||
|
||||
VOCAB_SIZE = 50304
|
||||
SEQ_LENGTH = 1024
|
||||
|
||||
TOTAL_BATCH_SIZE = 256
|
||||
LEARNING_RATE = 0.00015
|
||||
WEIGHT_DECAY = 1e-2
|
||||
|
||||
TENSOR_PARALLEL_SIZE = 2
|
||||
TENSOR_PARALLEL_MODE = '1d'
|
||||
|
||||
NUM_EPOCHS = 60
|
||||
WARMUP_EPOCHS = int(NUM_EPOCHS * 0.36)
|
||||
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE),
|
||||
)
|
||||
|
||||
fp16 = dict(mode=AMP_TYPE.TORCH, )
|
||||
|
||||
gradient_accumulation = 2
|
||||
|
||||
BATCH_SIZE = TOTAL_BATCH_SIZE // gradient_accumulation
|
||||
|
||||
clip_grad_norm = 1.0
|
||||
|
||||
LOG_PATH = f"./gpt2_{TENSOR_PARALLEL_MODE}_tp{TENSOR_PARALLEL_SIZE}_bs{BATCH_SIZE}_lr{LEARNING_RATE}_accum{gradient_accumulation}_clip_grad{clip_grad_norm}/"
|
|
@ -1,29 +0,0 @@
|
|||
from colossalai.amp import AMP_TYPE
|
||||
|
||||
VOCAB_SIZE = 50304
|
||||
SEQ_LENGTH = 1024
|
||||
|
||||
TOTAL_BATCH_SIZE = 256
|
||||
LEARNING_RATE = 0.00015
|
||||
WEIGHT_DECAY = 1e-2
|
||||
|
||||
TENSOR_PARALLEL_SIZE = 4
|
||||
TENSOR_PARALLEL_MODE = '2d'
|
||||
|
||||
NUM_EPOCHS = 60
|
||||
WARMUP_EPOCHS = int(NUM_EPOCHS * 0.36)
|
||||
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE),
|
||||
)
|
||||
|
||||
fp16 = dict(mode=AMP_TYPE.TORCH, )
|
||||
|
||||
gradient_accumulation = 1
|
||||
|
||||
BATCH_SIZE = TOTAL_BATCH_SIZE // gradient_accumulation
|
||||
|
||||
clip_grad_norm = 1.0
|
||||
|
||||
LOG_PATH = f"./gpt2_{TENSOR_PARALLEL_MODE}_tp{TENSOR_PARALLEL_SIZE}_bs{BATCH_SIZE}_lr{LEARNING_RATE}_accum{gradient_accumulation}_clip_grad{clip_grad_norm}/"
|
|
@ -1,30 +0,0 @@
|
|||
from colossalai.amp import AMP_TYPE
|
||||
|
||||
VOCAB_SIZE = 50304
|
||||
SEQ_LENGTH = 1024
|
||||
|
||||
TOTAL_BATCH_SIZE = 256
|
||||
LEARNING_RATE = 0.00015
|
||||
WEIGHT_DECAY = 1e-2
|
||||
|
||||
TENSOR_PARALLEL_SIZE = 4
|
||||
DEPTH = 1
|
||||
TENSOR_PARALLEL_MODE = '2.5d'
|
||||
|
||||
NUM_EPOCHS = 60
|
||||
WARMUP_EPOCHS = int(NUM_EPOCHS * 0.36)
|
||||
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE, depth=DEPTH),
|
||||
)
|
||||
|
||||
fp16 = dict(mode=AMP_TYPE.TORCH, )
|
||||
|
||||
gradient_accumulation = 1
|
||||
|
||||
BATCH_SIZE = TOTAL_BATCH_SIZE // gradient_accumulation
|
||||
|
||||
clip_grad_norm = 1.0
|
||||
|
||||
LOG_PATH = f"./gpt2_{TENSOR_PARALLEL_MODE}_tp{TENSOR_PARALLEL_SIZE}_bs{BATCH_SIZE}_lr{LEARNING_RATE}_accum{gradient_accumulation}_clip_grad{clip_grad_norm}/"
|
|
@ -1,29 +0,0 @@
|
|||
from colossalai.amp import AMP_TYPE
|
||||
|
||||
VOCAB_SIZE = 50304
|
||||
SEQ_LENGTH = 1024
|
||||
|
||||
TOTAL_BATCH_SIZE = 256
|
||||
LEARNING_RATE = 0.00015
|
||||
WEIGHT_DECAY = 1e-2
|
||||
|
||||
TENSOR_PARALLEL_SIZE = 8
|
||||
TENSOR_PARALLEL_MODE = '3d'
|
||||
|
||||
NUM_EPOCHS = 60
|
||||
WARMUP_EPOCHS = int(NUM_EPOCHS * 0.36)
|
||||
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE),
|
||||
)
|
||||
|
||||
fp16 = dict(mode=AMP_TYPE.TORCH, )
|
||||
|
||||
gradient_accumulation = 1
|
||||
|
||||
BATCH_SIZE = TOTAL_BATCH_SIZE // gradient_accumulation
|
||||
|
||||
clip_grad_norm = 1.0
|
||||
|
||||
LOG_PATH = f"./gpt2_{TENSOR_PARALLEL_MODE}_tp{TENSOR_PARALLEL_SIZE}_bs{BATCH_SIZE}_lr{LEARNING_RATE}_accum{gradient_accumulation}_clip_grad{clip_grad_norm}/"
|
|
@ -1,29 +0,0 @@
|
|||
from colossalai.amp import AMP_TYPE
|
||||
|
||||
VOCAB_SIZE = 50304
|
||||
SEQ_LENGTH = 1024
|
||||
|
||||
TOTAL_BATCH_SIZE = 256
|
||||
LEARNING_RATE = 0.00015
|
||||
WEIGHT_DECAY = 1e-2
|
||||
|
||||
TENSOR_PARALLEL_SIZE = 1
|
||||
TENSOR_PARALLEL_MODE = None
|
||||
|
||||
NUM_EPOCHS = 60
|
||||
WARMUP_EPOCHS = int(NUM_EPOCHS * 0.36)
|
||||
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE),
|
||||
)
|
||||
|
||||
fp16 = dict(mode=AMP_TYPE.TORCH, )
|
||||
|
||||
gradient_accumulation = 1
|
||||
|
||||
BATCH_SIZE = TOTAL_BATCH_SIZE // gradient_accumulation
|
||||
|
||||
clip_grad_norm = 1.0
|
||||
|
||||
LOG_PATH = f"./gpt2_{TENSOR_PARALLEL_MODE}_tp{TENSOR_PARALLEL_SIZE}_bs{BATCH_SIZE}_lr{LEARNING_RATE}_accum{gradient_accumulation}_clip_grad{clip_grad_norm}/"
|
|
@ -1,37 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
import torch
|
||||
from colossalai.registry import DATASETS
|
||||
from torch.utils.data import Dataset
|
||||
from transformers import GPT2Tokenizer
|
||||
|
||||
|
||||
@DATASETS.register_module
|
||||
class WebtextDataset(Dataset):
|
||||
def __init__(self, path, seq_len=1024) -> None:
|
||||
super().__init__()
|
||||
root = os.path.dirname(path)
|
||||
encoded_data_cache_path = os.path.join(root, f'gpt_webtext_{seq_len}.pt')
|
||||
if os.path.isfile(encoded_data_cache_path):
|
||||
seq_len_, data, attention_mask = torch.load(encoded_data_cache_path)
|
||||
if seq_len_ == seq_len:
|
||||
self.data = data
|
||||
self.attention_mask = attention_mask
|
||||
return
|
||||
raw_data = []
|
||||
with open(path) as f:
|
||||
for line in f.readlines():
|
||||
raw_data.append(json.loads(line)['text'])
|
||||
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
|
||||
tokenizer.pad_token = tokenizer.unk_token
|
||||
encoded_data = tokenizer(raw_data, padding=True, truncation=True, max_length=seq_len, return_tensors='pt')
|
||||
self.data = encoded_data['input_ids']
|
||||
self.attention_mask = encoded_data['attention_mask']
|
||||
torch.save((seq_len, self.data, self.attention_mask), encoded_data_cache_path)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.data)
|
||||
|
||||
def __getitem__(self, index):
|
||||
return (self.data[index], self.attention_mask[index]), self.data[index]
|
|
@ -1,105 +0,0 @@
|
|||
import contextlib
|
||||
import os
|
||||
|
||||
import colossalai
|
||||
import torch
|
||||
from colossalai.core import global_context as gpc
|
||||
from colossalai.engine.schedule import (InterleavedPipelineSchedule, PipelineSchedule)
|
||||
from colossalai.logging import get_dist_logger
|
||||
from colossalai.nn import CosineAnnealingWarmupLR
|
||||
from colossalai.trainer import Trainer, hooks
|
||||
from colossalai.utils import MultiTimer, get_dataloader
|
||||
from colossalai.zero import zero3_model_context
|
||||
from model_zoo.gpt import GPTLMLoss, gpt2_small, gpt2_medium, gpt2_large, gpt2_xl
|
||||
|
||||
from data import WebtextDataset
|
||||
|
||||
|
||||
def train_gpt():
|
||||
args = colossalai.get_default_parser().parse_args()
|
||||
# standard launch
|
||||
# colossalai.launch(config=args.config,
|
||||
# rank=args.rank,
|
||||
# world_size=args.world_size,
|
||||
# local_rank=args.local_rank,
|
||||
# host=args.host,
|
||||
# port=args.port)
|
||||
|
||||
# launch from torchrun
|
||||
colossalai.launch_from_torch(config=args.config)
|
||||
|
||||
logger = get_dist_logger()
|
||||
if hasattr(gpc.config, 'LOG_PATH'):
|
||||
if gpc.get_global_rank() == 0:
|
||||
log_path = gpc.config.LOG_PATH
|
||||
if not os.path.exists(log_path):
|
||||
os.mkdir(log_path)
|
||||
logger.log_to_file(log_path)
|
||||
|
||||
train_dataset = WebtextDataset(os.environ['DATA'], seq_len=gpc.config.SEQ_LENGTH)
|
||||
train_dataloader = get_dataloader(train_dataset,
|
||||
seed=42,
|
||||
batch_size=gpc.config.BATCH_SIZE // gpc.data_parallel_size,
|
||||
pin_memory=True,
|
||||
shuffle=True,
|
||||
drop_last=True)
|
||||
logger.info(f'Loaded {len(train_dataset)}/{len(train_dataloader)} samples/batches', ranks=[0])
|
||||
|
||||
# zero3 under test
|
||||
# use_zero3 = hasattr(gpc.config, 'zero') and gpc.config.zero.level == 3
|
||||
# cm = zero3_model_context() if use_zero3 else contextlib.nullcontext()
|
||||
# with cm:
|
||||
# model = gpc.config.model.pop('type')(**gpc.config.model)
|
||||
|
||||
model = gpt2_medium(vocab_size=gpc.config.VOCAB_SIZE,
|
||||
max_position_embeddings=gpc.config.SEQ_LENGTH,
|
||||
checkpoint=True)
|
||||
|
||||
criterion = GPTLMLoss()
|
||||
|
||||
optimizer = torch.optim.Adam(model.parameters(), lr=0.00015, weight_decay=1e-2)
|
||||
|
||||
steps_per_epoch = len(train_dataloader) // gpc.config.gradient_accumulation
|
||||
|
||||
lr_scheduler = CosineAnnealingWarmupLR(optimizer=optimizer,
|
||||
total_steps=gpc.config.NUM_EPOCHS * steps_per_epoch,
|
||||
warmup_steps=gpc.config.WARMUP_EPOCHS * steps_per_epoch,
|
||||
eta_min=1e-5)
|
||||
|
||||
engine, train_dataloader, _, lr_scheduler = colossalai.initialize(model=model,
|
||||
optimizer=optimizer,
|
||||
criterion=criterion,
|
||||
train_dataloader=train_dataloader,
|
||||
lr_scheduler=lr_scheduler)
|
||||
|
||||
# pipeline under test
|
||||
# num_model_chunks = getattr(gpc.config.model, 'num_chunks', 1)
|
||||
# if num_model_chunks > 1:
|
||||
# logger.info('Build InterleavedPipelineSchedule', ranks=[0])
|
||||
# schedule = InterleavedPipelineSchedule(gpc.config.NUM_MICRO_BATCHES, num_model_chunks)
|
||||
# else:
|
||||
# logger.info('Build PipelineSchedule', ranks=[0])
|
||||
# schedule = PipelineSchedule(gpc.config.NUM_MICRO_BATCHES)
|
||||
|
||||
timer = MultiTimer()
|
||||
|
||||
trainer = Trainer(engine=engine, logger=logger, timer=timer)
|
||||
|
||||
hook_list = [
|
||||
hooks.LogMetricByEpochHook(logger=logger),
|
||||
hooks.LogMetricByStepHook(),
|
||||
hooks.LossHook(),
|
||||
hooks.ThroughputHook(),
|
||||
hooks.LRSchedulerHook(lr_scheduler=lr_scheduler, by_epoch=False),
|
||||
# hooks.TensorboardHook(log_dir='./tb_logs', ranks=[0]),
|
||||
# hooks.LogMemoryByEpochHook(logger),
|
||||
# hooks.LogTimingByEpochHook(timer, logger),
|
||||
# hooks.SaveCheckpointHook(checkpoint_dir='./ckpt')
|
||||
]
|
||||
|
||||
logger.info("Training start", ranks=[0])
|
||||
trainer.fit(train_dataloader=train_dataloader, epochs=gpc.config.NUM_EPOCHS, hooks=hook_list, display_progress=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
train_gpt()
|
|
@ -1,26 +0,0 @@
|
|||
from colossalai.amp import AMP_TYPE
|
||||
|
||||
TOTAL_BATCH_SIZE = 4096
|
||||
LEARNING_RATE = 3e-3
|
||||
WEIGHT_DECAY = 0.3
|
||||
|
||||
TENSOR_PARALLEL_SIZE = 2
|
||||
TENSOR_PARALLEL_MODE = '1d'
|
||||
|
||||
NUM_EPOCHS = 300
|
||||
WARMUP_EPOCHS = 32
|
||||
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE),
|
||||
)
|
||||
|
||||
fp16 = dict(mode=AMP_TYPE.TORCH, )
|
||||
|
||||
gradient_accumulation = 2
|
||||
|
||||
BATCH_SIZE = TOTAL_BATCH_SIZE // gradient_accumulation
|
||||
|
||||
clip_grad_norm = 1.0
|
||||
|
||||
LOG_PATH = f"./vit_{TENSOR_PARALLEL_MODE}_imagenet100_tp{TENSOR_PARALLEL_SIZE}_bs{BATCH_SIZE}_lr{LEARNING_RATE}_{fp16['mode']}_clip_grad{clip_grad_norm}/"
|
|
@ -1,26 +0,0 @@
|
|||
from colossalai.amp import AMP_TYPE
|
||||
|
||||
TOTAL_BATCH_SIZE = 4096
|
||||
LEARNING_RATE = 3e-3
|
||||
WEIGHT_DECAY = 0.3
|
||||
|
||||
TENSOR_PARALLEL_SIZE = 4
|
||||
TENSOR_PARALLEL_MODE = '2d'
|
||||
|
||||
NUM_EPOCHS = 300
|
||||
WARMUP_EPOCHS = 32
|
||||
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE),
|
||||
)
|
||||
|
||||
fp16 = dict(mode=AMP_TYPE.TORCH, )
|
||||
|
||||
gradient_accumulation = 2
|
||||
|
||||
BATCH_SIZE = TOTAL_BATCH_SIZE // gradient_accumulation
|
||||
|
||||
clip_grad_norm = 1.0
|
||||
|
||||
LOG_PATH = f"./vit_{TENSOR_PARALLEL_MODE}_imagenet100_tp{TENSOR_PARALLEL_SIZE}_bs{BATCH_SIZE}_lr{LEARNING_RATE}_{fp16['mode']}_clip_grad{clip_grad_norm}/"
|
|
@ -1,27 +0,0 @@
|
|||
from colossalai.amp import AMP_TYPE
|
||||
|
||||
TOTAL_BATCH_SIZE = 4096
|
||||
LEARNING_RATE = 3e-3
|
||||
WEIGHT_DECAY = 0.3
|
||||
|
||||
TENSOR_PARALLEL_SIZE = 4
|
||||
DEPTH = 1
|
||||
TENSOR_PARALLEL_MODE = '2.5d'
|
||||
|
||||
NUM_EPOCHS = 300
|
||||
WARMUP_EPOCHS = 32
|
||||
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE, depth=DEPTH),
|
||||
)
|
||||
|
||||
fp16 = dict(mode=AMP_TYPE.TORCH, )
|
||||
|
||||
gradient_accumulation = 2
|
||||
|
||||
BATCH_SIZE = TOTAL_BATCH_SIZE // gradient_accumulation
|
||||
|
||||
clip_grad_norm = 1.0
|
||||
|
||||
LOG_PATH = f"./vit_{TENSOR_PARALLEL_MODE}_imagenet100_tp{TENSOR_PARALLEL_SIZE}_bs{BATCH_SIZE}_lr{LEARNING_RATE}_{fp16['mode']}_clip_grad{clip_grad_norm}/"
|
|
@ -1,26 +0,0 @@
|
|||
from colossalai.amp import AMP_TYPE
|
||||
|
||||
TOTAL_BATCH_SIZE = 4096
|
||||
LEARNING_RATE = 3e-3
|
||||
WEIGHT_DECAY = 0.3
|
||||
|
||||
TENSOR_PARALLEL_SIZE = 8
|
||||
TENSOR_PARALLEL_MODE = '3d'
|
||||
|
||||
NUM_EPOCHS = 300
|
||||
WARMUP_EPOCHS = 32
|
||||
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE),
|
||||
)
|
||||
|
||||
fp16 = dict(mode=AMP_TYPE.TORCH, )
|
||||
|
||||
gradient_accumulation = 2
|
||||
|
||||
BATCH_SIZE = TOTAL_BATCH_SIZE // gradient_accumulation
|
||||
|
||||
clip_grad_norm = 1.0
|
||||
|
||||
LOG_PATH = f"./vit_{TENSOR_PARALLEL_MODE}_imagenet100_tp{TENSOR_PARALLEL_SIZE}_bs{BATCH_SIZE}_lr{LEARNING_RATE}_{fp16['mode']}_clip_grad{clip_grad_norm}/"
|
|
@ -1,26 +0,0 @@
|
|||
from colossalai.amp import AMP_TYPE
|
||||
|
||||
TOTAL_BATCH_SIZE = 4096
|
||||
LEARNING_RATE = 3e-3
|
||||
WEIGHT_DECAY = 0.3
|
||||
|
||||
TENSOR_PARALLEL_SIZE = 1
|
||||
TENSOR_PARALLEL_MODE = None
|
||||
|
||||
NUM_EPOCHS = 300
|
||||
WARMUP_EPOCHS = 32
|
||||
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE),
|
||||
)
|
||||
|
||||
fp16 = dict(mode=AMP_TYPE.TORCH, )
|
||||
|
||||
gradient_accumulation = 2
|
||||
|
||||
BATCH_SIZE = TOTAL_BATCH_SIZE // gradient_accumulation
|
||||
|
||||
clip_grad_norm = 1.0
|
||||
|
||||
LOG_PATH = f"./vit_{TENSOR_PARALLEL_MODE}_imagenet100_tp{TENSOR_PARALLEL_SIZE}_bs{BATCH_SIZE}_lr{LEARNING_RATE}_{fp16['mode']}_clip_grad{clip_grad_norm}/"
|
|
@ -1,207 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
import glob
|
||||
import os
|
||||
|
||||
import colossalai
|
||||
import nvidia.dali.fn as fn
|
||||
import nvidia.dali.tfrecord as tfrec
|
||||
import torch
|
||||
from colossalai.builder import *
|
||||
from colossalai.context import ParallelMode
|
||||
from colossalai.core import global_context as gpc
|
||||
from colossalai.logging import get_dist_logger
|
||||
from colossalai.nn import Accuracy, CrossEntropyLoss
|
||||
from colossalai.nn.lr_scheduler import CosineAnnealingWarmupLR
|
||||
from colossalai.trainer import Trainer, hooks
|
||||
from colossalai.utils import MultiTimer
|
||||
from model_zoo.vit import vit_small_patch16_224
|
||||
from nvidia.dali import types
|
||||
from nvidia.dali.pipeline import Pipeline
|
||||
from nvidia.dali.plugin.pytorch import DALIClassificationIterator
|
||||
|
||||
DATASET_PATH = str(os.environ['DATA'])
|
||||
|
||||
TRAIN_RECS = DATASET_PATH + '/train/*'
|
||||
VAL_RECS = DATASET_PATH + '/validation/*'
|
||||
TRAIN_IDX = DATASET_PATH + '/idx_files/train/*'
|
||||
VAL_IDX = DATASET_PATH + '/idx_files/validation/*'
|
||||
|
||||
|
||||
class DaliDataloader(DALIClassificationIterator):
|
||||
def __init__(self,
|
||||
tfrec_filenames,
|
||||
tfrec_idx_filenames,
|
||||
shard_id=0,
|
||||
num_shards=1,
|
||||
batch_size=128,
|
||||
num_threads=4,
|
||||
resize=256,
|
||||
crop=224,
|
||||
prefetch=2,
|
||||
training=True,
|
||||
gpu_aug=False,
|
||||
cuda=True):
|
||||
pipe = Pipeline(batch_size=batch_size,
|
||||
num_threads=num_threads,
|
||||
device_id=torch.cuda.current_device() if cuda else None,
|
||||
seed=1024)
|
||||
with pipe:
|
||||
inputs = fn.readers.tfrecord(path=tfrec_filenames,
|
||||
index_path=tfrec_idx_filenames,
|
||||
random_shuffle=training,
|
||||
shard_id=shard_id,
|
||||
num_shards=num_shards,
|
||||
initial_fill=10000,
|
||||
read_ahead=True,
|
||||
prefetch_queue_depth=prefetch,
|
||||
name='Reader',
|
||||
features={
|
||||
'image/encoded': tfrec.FixedLenFeature((), tfrec.string, ""),
|
||||
'image/class/label': tfrec.FixedLenFeature([1], tfrec.int64, -1),
|
||||
})
|
||||
images = inputs["image/encoded"]
|
||||
|
||||
if training:
|
||||
images = fn.decoders.image(images, device='mixed' if gpu_aug else 'cpu', output_type=types.RGB)
|
||||
images = fn.random_resized_crop(images, size=crop, device='gpu' if gpu_aug else 'cpu')
|
||||
flip_lr = fn.random.coin_flip(probability=0.5)
|
||||
else:
|
||||
# decode jpeg and resize
|
||||
images = fn.decoders.image(images, device='mixed' if gpu_aug else 'cpu', output_type=types.RGB)
|
||||
images = fn.resize(images,
|
||||
device='gpu' if gpu_aug else 'cpu',
|
||||
resize_x=resize,
|
||||
resize_y=resize,
|
||||
dtype=types.FLOAT,
|
||||
interp_type=types.INTERP_TRIANGULAR)
|
||||
flip_lr = False
|
||||
|
||||
# center crop and normalise
|
||||
images = fn.crop_mirror_normalize(images,
|
||||
dtype=types.FLOAT,
|
||||
crop=(crop, crop),
|
||||
mean=[127.5],
|
||||
std=[127.5],
|
||||
mirror=flip_lr)
|
||||
label = inputs["image/class/label"] - 1 # 0-999
|
||||
# LSG: element_extract will raise exception, let's flatten outside
|
||||
# label = fn.element_extract(label, element_map=0) # Flatten
|
||||
if cuda: # transfer data to gpu
|
||||
pipe.set_outputs(images.gpu(), label.gpu())
|
||||
else:
|
||||
pipe.set_outputs(images, label)
|
||||
|
||||
pipe.build()
|
||||
last_batch_policy = 'DROP' if training else 'PARTIAL'
|
||||
super().__init__(pipe, reader_name="Reader", auto_reset=True, last_batch_policy=last_batch_policy)
|
||||
|
||||
def __iter__(self):
|
||||
# if not reset (after an epoch), reset; if just initialize, ignore
|
||||
if self._counter >= self._size or self._size < 0:
|
||||
self.reset()
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
data = super().__next__()
|
||||
img, label = data[0]['data'], data[0]['label']
|
||||
label = label.squeeze()
|
||||
return (img, ), (label, )
|
||||
|
||||
|
||||
def build_dali_train(batch_size):
|
||||
return DaliDataloader(
|
||||
sorted(glob.glob(TRAIN_RECS)),
|
||||
sorted(glob.glob(TRAIN_IDX)),
|
||||
batch_size=batch_size,
|
||||
shard_id=gpc.get_local_rank(ParallelMode.DATA),
|
||||
num_shards=gpc.get_world_size(ParallelMode.DATA),
|
||||
training=True,
|
||||
gpu_aug=True,
|
||||
cuda=True,
|
||||
)
|
||||
|
||||
|
||||
def build_dali_test(batch_size):
|
||||
return DaliDataloader(
|
||||
sorted(glob.glob(VAL_RECS)),
|
||||
sorted(glob.glob(VAL_IDX)),
|
||||
batch_size=batch_size,
|
||||
shard_id=gpc.get_local_rank(ParallelMode.DATA),
|
||||
num_shards=gpc.get_world_size(ParallelMode.DATA),
|
||||
training=False,
|
||||
gpu_aug=True,
|
||||
cuda=True,
|
||||
)
|
||||
|
||||
|
||||
def train_imagenet():
|
||||
args = colossalai.get_default_parser().parse_args()
|
||||
# standard launch
|
||||
# colossalai.launch(config=args.config,
|
||||
# rank=args.rank,
|
||||
# world_size=args.world_size,
|
||||
# local_rank=args.local_rank,
|
||||
# host=args.host,
|
||||
# port=args.port)
|
||||
|
||||
# launch from torchrun
|
||||
colossalai.launch_from_torch(config=args.config)
|
||||
|
||||
logger = get_dist_logger()
|
||||
if hasattr(gpc.config, 'LOG_PATH'):
|
||||
if gpc.get_global_rank() == 0:
|
||||
log_path = gpc.config.LOG_PATH
|
||||
if not os.path.exists(log_path):
|
||||
os.mkdir(log_path)
|
||||
logger.log_to_file(log_path)
|
||||
|
||||
model = vit_small_patch16_224(num_classes=100, init_method='jax')
|
||||
|
||||
train_dataloader = build_dali_train(gpc.config.BATCH_SIZE // gpc.data_parallel_size)
|
||||
test_dataloader = build_dali_test(gpc.config.BATCH_SIZE // gpc.data_parallel_size)
|
||||
|
||||
criterion = CrossEntropyLoss(label_smoothing=0.1)
|
||||
|
||||
optimizer = torch.optim.AdamW(model.parameters(), lr=gpc.config.LEARNING_RATE, weight_decay=gpc.config.WEIGHT_DECAY)
|
||||
|
||||
lr_scheduler = CosineAnnealingWarmupLR(optimizer=optimizer,
|
||||
total_steps=gpc.config.NUM_EPOCHS,
|
||||
warmup_steps=gpc.config.WARMUP_EPOCHS)
|
||||
|
||||
engine, train_dataloader, test_dataloader, _ = colossalai.initialize(model=model,
|
||||
optimizer=optimizer,
|
||||
criterion=criterion,
|
||||
train_dataloader=train_dataloader,
|
||||
test_dataloader=test_dataloader)
|
||||
|
||||
logger.info("Engine is built", ranks=[0])
|
||||
|
||||
timer = MultiTimer()
|
||||
|
||||
trainer = Trainer(engine=engine, logger=logger, timer=timer)
|
||||
logger.info("Trainer is built", ranks=[0])
|
||||
|
||||
hook_list = [
|
||||
hooks.LogMetricByEpochHook(logger=logger),
|
||||
hooks.LogMetricByStepHook(),
|
||||
# hooks.LogTimingByEpochHook(timer=timer, logger=logger),
|
||||
# hooks.LogMemoryByEpochHook(logger=logger),
|
||||
hooks.AccuracyHook(accuracy_func=Accuracy()),
|
||||
hooks.LossHook(),
|
||||
hooks.ThroughputHook(),
|
||||
hooks.LRSchedulerHook(lr_scheduler=lr_scheduler, by_epoch=True)
|
||||
]
|
||||
|
||||
logger.info("Train start", ranks=[0])
|
||||
trainer.fit(train_dataloader=train_dataloader,
|
||||
test_dataloader=test_dataloader,
|
||||
epochs=gpc.config.NUM_EPOCHS,
|
||||
hooks=hook_list,
|
||||
display_progress=True,
|
||||
test_interval=1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
train_imagenet()
|
|
@ -1,26 +0,0 @@
|
|||
from colossalai.amp import AMP_TYPE
|
||||
|
||||
TOTAL_BATCH_SIZE = 4096
|
||||
LEARNING_RATE = 3e-3
|
||||
WEIGHT_DECAY = 0.3
|
||||
|
||||
TENSOR_PARALLEL_SIZE = 2
|
||||
TENSOR_PARALLEL_MODE = '1d'
|
||||
|
||||
NUM_EPOCHS = 300
|
||||
WARMUP_EPOCHS = 32
|
||||
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE),
|
||||
)
|
||||
|
||||
fp16 = dict(mode=AMP_TYPE.TORCH, )
|
||||
|
||||
gradient_accumulation = 2
|
||||
|
||||
BATCH_SIZE = TOTAL_BATCH_SIZE // gradient_accumulation
|
||||
|
||||
clip_grad_norm = 1.0
|
||||
|
||||
LOG_PATH = f"./vit_{TENSOR_PARALLEL_MODE}_imagenet1k_tp{TENSOR_PARALLEL_SIZE}_bs{BATCH_SIZE}_lr{LEARNING_RATE}_{fp16['mode']}_clip_grad{clip_grad_norm}/"
|
|
@ -1,26 +0,0 @@
|
|||
from colossalai.amp import AMP_TYPE
|
||||
|
||||
TOTAL_BATCH_SIZE = 4096
|
||||
LEARNING_RATE = 3e-3
|
||||
WEIGHT_DECAY = 0.3
|
||||
|
||||
TENSOR_PARALLEL_SIZE = 4
|
||||
TENSOR_PARALLEL_MODE = '2d'
|
||||
|
||||
NUM_EPOCHS = 300
|
||||
WARMUP_EPOCHS = 32
|
||||
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE),
|
||||
)
|
||||
|
||||
fp16 = dict(mode=AMP_TYPE.TORCH, )
|
||||
|
||||
gradient_accumulation = 2
|
||||
|
||||
BATCH_SIZE = TOTAL_BATCH_SIZE // gradient_accumulation
|
||||
|
||||
clip_grad_norm = 1.0
|
||||
|
||||
LOG_PATH = f"./vit_{TENSOR_PARALLEL_MODE}_imagenet1k_tp{TENSOR_PARALLEL_SIZE}_bs{BATCH_SIZE}_lr{LEARNING_RATE}_{fp16['mode']}_clip_grad{clip_grad_norm}/"
|
|
@ -1,27 +0,0 @@
|
|||
from colossalai.amp import AMP_TYPE
|
||||
|
||||
TOTAL_BATCH_SIZE = 4096
|
||||
LEARNING_RATE = 3e-3
|
||||
WEIGHT_DECAY = 0.3
|
||||
|
||||
TENSOR_PARALLEL_SIZE = 4
|
||||
DEPTH = 1
|
||||
TENSOR_PARALLEL_MODE = '2.5d'
|
||||
|
||||
NUM_EPOCHS = 300
|
||||
WARMUP_EPOCHS = 32
|
||||
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE, depth=DEPTH),
|
||||
)
|
||||
|
||||
fp16 = dict(mode=AMP_TYPE.TORCH, )
|
||||
|
||||
gradient_accumulation = 2
|
||||
|
||||
BATCH_SIZE = TOTAL_BATCH_SIZE // gradient_accumulation
|
||||
|
||||
clip_grad_norm = 1.0
|
||||
|
||||
LOG_PATH = f"./vit_{TENSOR_PARALLEL_MODE}_imagenet1k_tp{TENSOR_PARALLEL_SIZE}_bs{BATCH_SIZE}_lr{LEARNING_RATE}_{fp16['mode']}_clip_grad{clip_grad_norm}/"
|
|
@ -1,26 +0,0 @@
|
|||
from colossalai.amp import AMP_TYPE
|
||||
|
||||
TOTAL_BATCH_SIZE = 4096
|
||||
LEARNING_RATE = 3e-3
|
||||
WEIGHT_DECAY = 0.3
|
||||
|
||||
TENSOR_PARALLEL_SIZE = 8
|
||||
TENSOR_PARALLEL_MODE = '3d'
|
||||
|
||||
NUM_EPOCHS = 300
|
||||
WARMUP_EPOCHS = 32
|
||||
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE),
|
||||
)
|
||||
|
||||
fp16 = dict(mode=AMP_TYPE.TORCH, )
|
||||
|
||||
gradient_accumulation = 2
|
||||
|
||||
BATCH_SIZE = TOTAL_BATCH_SIZE // gradient_accumulation
|
||||
|
||||
clip_grad_norm = 1.0
|
||||
|
||||
LOG_PATH = f"./vit_{TENSOR_PARALLEL_MODE}_imagenet1k_tp{TENSOR_PARALLEL_SIZE}_bs{BATCH_SIZE}_lr{LEARNING_RATE}_{fp16['mode']}_clip_grad{clip_grad_norm}/"
|
|
@ -1,26 +0,0 @@
|
|||
from colossalai.amp import AMP_TYPE
|
||||
|
||||
TOTAL_BATCH_SIZE = 4096
|
||||
LEARNING_RATE = 3e-3
|
||||
WEIGHT_DECAY = 0.3
|
||||
|
||||
TENSOR_PARALLEL_SIZE = 1
|
||||
TENSOR_PARALLEL_MODE = None
|
||||
|
||||
NUM_EPOCHS = 300
|
||||
WARMUP_EPOCHS = 32
|
||||
|
||||
parallel = dict(
|
||||
pipeline=1,
|
||||
tensor=dict(mode=TENSOR_PARALLEL_MODE, size=TENSOR_PARALLEL_SIZE),
|
||||
)
|
||||
|
||||
fp16 = dict(mode=AMP_TYPE.TORCH, )
|
||||
|
||||
gradient_accumulation = 2
|
||||
|
||||
BATCH_SIZE = TOTAL_BATCH_SIZE // gradient_accumulation
|
||||
|
||||
clip_grad_norm = 1.0
|
||||
|
||||
LOG_PATH = f"./vit_{TENSOR_PARALLEL_MODE}_imagenet1k_tp{TENSOR_PARALLEL_SIZE}_bs{BATCH_SIZE}_lr{LEARNING_RATE}_{fp16['mode']}_clip_grad{clip_grad_norm}/"
|
|
@ -1,207 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
import glob
|
||||
import os
|
||||
|
||||
import colossalai
|
||||
import nvidia.dali.fn as fn
|
||||
import nvidia.dali.tfrecord as tfrec
|
||||
import torch
|
||||
from colossalai.builder import *
|
||||
from colossalai.context import ParallelMode
|
||||
from colossalai.core import global_context as gpc
|
||||
from colossalai.logging import get_dist_logger
|
||||
from colossalai.nn import Accuracy, CrossEntropyLoss
|
||||
from colossalai.nn.lr_scheduler import CosineAnnealingWarmupLR
|
||||
from colossalai.trainer import Trainer, hooks
|
||||
from colossalai.utils import MultiTimer
|
||||
from model_zoo.vit import vit_small_patch16_224
|
||||
from nvidia.dali import types
|
||||
from nvidia.dali.pipeline import Pipeline
|
||||
from nvidia.dali.plugin.pytorch import DALIClassificationIterator
|
||||
|
||||
DATASET_PATH = str(os.environ['DATA'])
|
||||
|
||||
TRAIN_RECS = DATASET_PATH + '/train/*'
|
||||
VAL_RECS = DATASET_PATH + '/validation/*'
|
||||
TRAIN_IDX = DATASET_PATH + '/idx_files/train/*'
|
||||
VAL_IDX = DATASET_PATH + '/idx_files/validation/*'
|
||||
|
||||
|
||||
class DaliDataloader(DALIClassificationIterator):
|
||||
def __init__(self,
|
||||
tfrec_filenames,
|
||||
tfrec_idx_filenames,
|
||||
shard_id=0,
|
||||
num_shards=1,
|
||||
batch_size=128,
|
||||
num_threads=4,
|
||||
resize=256,
|
||||
crop=224,
|
||||
prefetch=2,
|
||||
training=True,
|
||||
gpu_aug=False,
|
||||
cuda=True):
|
||||
pipe = Pipeline(batch_size=batch_size,
|
||||
num_threads=num_threads,
|
||||
device_id=torch.cuda.current_device() if cuda else None,
|
||||
seed=1024)
|
||||
with pipe:
|
||||
inputs = fn.readers.tfrecord(path=tfrec_filenames,
|
||||
index_path=tfrec_idx_filenames,
|
||||
random_shuffle=training,
|
||||
shard_id=shard_id,
|
||||
num_shards=num_shards,
|
||||
initial_fill=10000,
|
||||
read_ahead=True,
|
||||
prefetch_queue_depth=prefetch,
|
||||
name='Reader',
|
||||
features={
|
||||
'image/encoded': tfrec.FixedLenFeature((), tfrec.string, ""),
|
||||
'image/class/label': tfrec.FixedLenFeature([1], tfrec.int64, -1),
|
||||
})
|
||||
images = inputs["image/encoded"]
|
||||
|
||||
if training:
|
||||
images = fn.decoders.image(images, device='mixed' if gpu_aug else 'cpu', output_type=types.RGB)
|
||||
images = fn.random_resized_crop(images, size=crop, device='gpu' if gpu_aug else 'cpu')
|
||||
flip_lr = fn.random.coin_flip(probability=0.5)
|
||||
else:
|
||||
# decode jpeg and resize
|
||||
images = fn.decoders.image(images, device='mixed' if gpu_aug else 'cpu', output_type=types.RGB)
|
||||
images = fn.resize(images,
|
||||
device='gpu' if gpu_aug else 'cpu',
|
||||
resize_x=resize,
|
||||
resize_y=resize,
|
||||
dtype=types.FLOAT,
|
||||
interp_type=types.INTERP_TRIANGULAR)
|
||||
flip_lr = False
|
||||
|
||||
# center crop and normalise
|
||||
images = fn.crop_mirror_normalize(images,
|
||||
dtype=types.FLOAT,
|
||||
crop=(crop, crop),
|
||||
mean=[127.5],
|
||||
std=[127.5],
|
||||
mirror=flip_lr)
|
||||
label = inputs["image/class/label"] - 1 # 0-999
|
||||
# LSG: element_extract will raise exception, let's flatten outside
|
||||
# label = fn.element_extract(label, element_map=0) # Flatten
|
||||
if cuda: # transfer data to gpu
|
||||
pipe.set_outputs(images.gpu(), label.gpu())
|
||||
else:
|
||||
pipe.set_outputs(images, label)
|
||||
|
||||
pipe.build()
|
||||
last_batch_policy = 'DROP' if training else 'PARTIAL'
|
||||
super().__init__(pipe, reader_name="Reader", auto_reset=True, last_batch_policy=last_batch_policy)
|
||||
|
||||
def __iter__(self):
|
||||
# if not reset (after an epoch), reset; if just initialize, ignore
|
||||
if self._counter >= self._size or self._size < 0:
|
||||
self.reset()
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
data = super().__next__()
|
||||
img, label = data[0]['data'], data[0]['label']
|
||||
label = label.squeeze()
|
||||
return (img, ), (label, )
|
||||
|
||||
|
||||
def build_dali_train(batch_size):
|
||||
return DaliDataloader(
|
||||
sorted(glob.glob(TRAIN_RECS)),
|
||||
sorted(glob.glob(TRAIN_IDX)),
|
||||
batch_size=batch_size,
|
||||
shard_id=gpc.get_local_rank(ParallelMode.DATA),
|
||||
num_shards=gpc.get_world_size(ParallelMode.DATA),
|
||||
training=True,
|
||||
gpu_aug=True,
|
||||
cuda=True,
|
||||
)
|
||||
|
||||
|
||||
def build_dali_test(batch_size):
|
||||
return DaliDataloader(
|
||||
sorted(glob.glob(VAL_RECS)),
|
||||
sorted(glob.glob(VAL_IDX)),
|
||||
batch_size=batch_size,
|
||||
shard_id=gpc.get_local_rank(ParallelMode.DATA),
|
||||
num_shards=gpc.get_world_size(ParallelMode.DATA),
|
||||
training=False,
|
||||
gpu_aug=True,
|
||||
cuda=True,
|
||||
)
|
||||
|
||||
|
||||
def train_imagenet():
|
||||
args = colossalai.get_default_parser().parse_args()
|
||||
# standard launch
|
||||
# colossalai.launch(config=args.config,
|
||||
# rank=args.rank,
|
||||
# world_size=args.world_size,
|
||||
# local_rank=args.local_rank,
|
||||
# host=args.host,
|
||||
# port=args.port)
|
||||
|
||||
# launch from torchrun
|
||||
colossalai.launch_from_torch(config=args.config)
|
||||
|
||||
logger = get_dist_logger()
|
||||
if hasattr(gpc.config, 'LOG_PATH'):
|
||||
if gpc.get_global_rank() == 0:
|
||||
log_path = gpc.config.LOG_PATH
|
||||
if not os.path.exists(log_path):
|
||||
os.mkdir(log_path)
|
||||
logger.log_to_file(log_path)
|
||||
|
||||
model = vit_small_patch16_224(num_classes=1000, init_method='jax')
|
||||
|
||||
train_dataloader = build_dali_train(gpc.config.BATCH_SIZE // gpc.data_parallel_size)
|
||||
test_dataloader = build_dali_test(gpc.config.BATCH_SIZE // gpc.data_parallel_size)
|
||||
|
||||
criterion = CrossEntropyLoss(label_smoothing=0.1)
|
||||
|
||||
optimizer = torch.optim.AdamW(model.parameters(), lr=gpc.config.LEARNING_RATE, weight_decay=gpc.config.WEIGHT_DECAY)
|
||||
|
||||
lr_scheduler = CosineAnnealingWarmupLR(optimizer=optimizer,
|
||||
total_steps=gpc.config.NUM_EPOCHS,
|
||||
warmup_steps=gpc.config.WARMUP_EPOCHS)
|
||||
|
||||
engine, train_dataloader, test_dataloader, _ = colossalai.initialize(model=model,
|
||||
optimizer=optimizer,
|
||||
criterion=criterion,
|
||||
train_dataloader=train_dataloader,
|
||||
test_dataloader=test_dataloader)
|
||||
|
||||
logger.info("Engine is built", ranks=[0])
|
||||
|
||||
timer = MultiTimer()
|
||||
|
||||
trainer = Trainer(engine=engine, logger=logger, timer=timer)
|
||||
logger.info("Trainer is built", ranks=[0])
|
||||
|
||||
hook_list = [
|
||||
hooks.LogMetricByEpochHook(logger=logger),
|
||||
hooks.LogMetricByStepHook(),
|
||||
# hooks.LogTimingByEpochHook(timer=timer, logger=logger),
|
||||
# hooks.LogMemoryByEpochHook(logger=logger),
|
||||
hooks.AccuracyHook(accuracy_func=Accuracy()),
|
||||
hooks.LossHook(),
|
||||
hooks.ThroughputHook(),
|
||||
hooks.LRSchedulerHook(lr_scheduler=lr_scheduler, by_epoch=True)
|
||||
]
|
||||
|
||||
logger.info("Train start", ranks=[0])
|
||||
trainer.fit(train_dataloader=train_dataloader,
|
||||
test_dataloader=test_dataloader,
|
||||
epochs=gpc.config.NUM_EPOCHS,
|
||||
hooks=hook_list,
|
||||
display_progress=True,
|
||||
test_interval=1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
train_imagenet()
|
Loading…
Reference in New Issue