mirror of
https://github.com/hpcaitech/ColossalAI.git
synced 2025-09-24 19:17:30 +00:00
Develop/experiments (#59)
* Add gradient accumulation, fix lr scheduler * fix FP16 optimizer and adapted torch amp with tensor parallel (#18) * fixed bugs in compatibility between torch amp and tensor parallel and performed some minor fixes * fixed trainer * Revert "fixed trainer" This reverts commit2e0b0b7699
. * improved consistency between trainer, engine and schedule (#23) Co-authored-by: 1SAA <c2h214748@gmail.com> * Split conv2d, class token, positional embedding in 2d, Fix random number in ddp Fix convergence in cifar10, Imagenet1000 * Integrate 1d tensor parallel in Colossal-AI (#39) * fixed 1D and 2D convergence (#38) * optimized 2D operations * fixed 1D ViT convergence problem * Feature/ddp (#49) * remove redundancy func in setup (#19) (#20) * use env to control the language of doc (#24) (#25) * Support TP-compatible Torch AMP and Update trainer API (#27) * Add gradient accumulation, fix lr scheduler * fix FP16 optimizer and adapted torch amp with tensor parallel (#18) * fixed bugs in compatibility between torch amp and tensor parallel and performed some minor fixes * fixed trainer * Revert "fixed trainer" This reverts commit2e0b0b7699
. * improved consistency between trainer, engine and schedule (#23) Co-authored-by: 1SAA <c2h214748@gmail.com> Co-authored-by: 1SAA <c2h214748@gmail.com> Co-authored-by: ver217 <lhx0217@gmail.com> * add an example of ViT-B/16 and remove w_norm clipping in LAMB (#29) * add explanation for ViT example (#35) (#36) * support torch ddp * fix loss accumulation * add log for ddp * change seed * modify timing hook Co-authored-by: Frank Lee <somerlee.9@gmail.com> Co-authored-by: 1SAA <c2h214748@gmail.com> Co-authored-by: binmakeswell <binmakeswell@gmail.com> * Feature/pipeline (#40) * remove redundancy func in setup (#19) (#20) * use env to control the language of doc (#24) (#25) * Support TP-compatible Torch AMP and Update trainer API (#27) * Add gradient accumulation, fix lr scheduler * fix FP16 optimizer and adapted torch amp with tensor parallel (#18) * fixed bugs in compatibility between torch amp and tensor parallel and performed some minor fixes * fixed trainer * Revert "fixed trainer" This reverts commit2e0b0b7699
. * improved consistency between trainer, engine and schedule (#23) Co-authored-by: 1SAA <c2h214748@gmail.com> Co-authored-by: 1SAA <c2h214748@gmail.com> Co-authored-by: ver217 <lhx0217@gmail.com> * add an example of ViT-B/16 and remove w_norm clipping in LAMB (#29) * add explanation for ViT example (#35) (#36) * optimize communication of pipeline parallel * fix grad clip for pipeline Co-authored-by: Frank Lee <somerlee.9@gmail.com> Co-authored-by: 1SAA <c2h214748@gmail.com> Co-authored-by: binmakeswell <binmakeswell@gmail.com> * optimized 3d layer to fix slow computation ; tested imagenet performance with 3d; reworked lr_scheduler config definition; fixed launch args; fixed some printing issues; simplified apis of 3d layers (#51) * Update 2.5d layer code to get a similar accuracy on imagenet-1k dataset * update api for better usability (#58) update api for better usability Co-authored-by: 1SAA <c2h214748@gmail.com> Co-authored-by: ver217 <lhx0217@gmail.com> Co-authored-by: puck_WCR <46049915+WANG-CR@users.noreply.github.com> Co-authored-by: binmakeswell <binmakeswell@gmail.com> Co-authored-by: アマデウス <kurisusnowdeng@users.noreply.github.com> Co-authored-by: BoxiangW <45734921+BoxiangW@users.noreply.github.com>
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
from .builder import (build_schedule, build_lr_scheduler, build_model, build_optimizer, build_optimizer_wrapper,
|
||||
build_layer, build_loss, build_hooks, build_dataset, build_transform, build_data_sampler,
|
||||
from .builder import (build_schedule, build_lr_scheduler, build_model, build_optimizer, build_layer,
|
||||
build_loss, build_hooks, build_dataset, build_transform, build_data_sampler,
|
||||
build_gradient_handler)
|
||||
from .pipeline import ModelInitializer
|
||||
from .pipeline import PipelineModelInitializer
|
||||
|
||||
__all__ = [
|
||||
'build_schedule', 'build_lr_scheduler', 'build_model', 'build_optimizer', 'build_optimizer_wrapper',
|
||||
'build_schedule', 'build_lr_scheduler', 'build_model', 'build_optimizer',
|
||||
'build_layer', 'build_loss', 'build_hooks', 'build_dataset', 'build_transform', 'build_data_sampler',
|
||||
'build_gradient_handler', 'ModelInitializer'
|
||||
'build_gradient_handler', 'PipelineModelInitializer'
|
||||
]
|
||||
|
@@ -106,7 +106,7 @@ def build_dataset(config):
|
||||
return build_from_registry(config, DATASETS)
|
||||
|
||||
|
||||
def build_optimizer(config, model, params: Iterable = None, need_module=False):
|
||||
def build_optimizer(config, model):
|
||||
"""Returns an optimizer object of :class:`torch.optim.Optimizer` constructed from `config`,
|
||||
'model' and 'params'.
|
||||
|
||||
@@ -115,23 +115,12 @@ def build_optimizer(config, model, params: Iterable = None, need_module=False):
|
||||
:type config: dict or :class:`colossalai.context.Config`
|
||||
:param model: A model containing parameters for the optimizer
|
||||
:type model: :class:`nn.Module`
|
||||
:param params: A dict containing parameters for the optimizer
|
||||
:type params: dict, optional
|
||||
:param need_module: Indicates whether the optimizer needs a module
|
||||
:type params: bool, optional
|
||||
:raises AssertionError: Raises an AssertionError if both `model` and `params` are None
|
||||
:return: An object of :class:`torch.optim.Optimizer`
|
||||
:rtype: :class:`torch.optim.Optimizer`
|
||||
"""
|
||||
assert model is not None or params is not None, 'arguments model and params can not both be None'
|
||||
if need_module:
|
||||
config['module'] = model
|
||||
elif model is not None:
|
||||
config['params'] = model.parameters()
|
||||
elif params is not None:
|
||||
config['params'] = params
|
||||
|
||||
return build_from_registry(config, OPTIMIZERS)
|
||||
config_ = config.copy()
|
||||
config_['params'] = model.parameters()
|
||||
return build_from_registry(config_, OPTIMIZERS)
|
||||
|
||||
|
||||
def build_gradient_handler(config, model, optimizer):
|
||||
@@ -149,8 +138,9 @@ def build_gradient_handler(config, model, optimizer):
|
||||
:rtype: :class:`BaseGradientHandler`
|
||||
"""
|
||||
config_ = config.copy()
|
||||
mod_type = config_.pop('type')
|
||||
return GRADIENT_HANDLER.get_module(mod_type)(model, optimizer, **config_)
|
||||
config_['model'] = model
|
||||
config_['optimizer'] = optimizer
|
||||
return build_from_registry(config_, GRADIENT_HANDLER)
|
||||
|
||||
|
||||
def build_hooks(config, trainer):
|
||||
@@ -164,8 +154,9 @@ def build_hooks(config, trainer):
|
||||
:return: An object of :class:`BaseHook`
|
||||
:rtype: :class:`BaseHook`
|
||||
"""
|
||||
config['trainer'] = trainer
|
||||
return build_from_registry(config, HOOKS)
|
||||
config_ = config.copy()
|
||||
config_['trainer'] = trainer
|
||||
return build_from_registry(config_, HOOKS)
|
||||
|
||||
|
||||
def build_transform(config):
|
||||
@@ -195,32 +186,8 @@ def build_data_sampler(config, dataset):
|
||||
:rtype: :class:`colossalai.nn.data.sampler.BaseSampler`
|
||||
"""
|
||||
config_ = config.copy()
|
||||
mod_type = config_.pop('type')
|
||||
return SAMPLERS.get_module(mod_type)(dataset, **config_)
|
||||
|
||||
|
||||
def build_optimizer_wrapper(config, optimizer, model=None):
|
||||
"""Returns an optimizer wrapper object of :class:`torch.optim.Optimizer` constructed
|
||||
from `config`, `model` and `optimizer`.
|
||||
|
||||
:param config: A python dict or a :class:`colossalai.context.Config` object
|
||||
containing information used in the construction of the return object
|
||||
:type config: dict or :class:`colossalai.context.Config`
|
||||
:param optimizer: An optimizer object containing parameters for the gradient handler
|
||||
:type optimizer: :class:`torch.optim.Optimizer`
|
||||
:param model: A model containing parameters for the gradient handler
|
||||
:type model: :class:`nn.Module`, optional
|
||||
:return: An object of :class:`torch.optim.Optimizer`
|
||||
:rtype: :class:`torch.optim.Optimizer`
|
||||
"""
|
||||
config_ = config.copy()
|
||||
mod_type = config_.pop('type')
|
||||
|
||||
# LSG: special treatment for zeor level 3
|
||||
if mod_type == 'ZeroRedundancyOptimizer_Level_3':
|
||||
return OPTIMIZER_WRAPPERS.get_module(mod_type)(model, optimizer, **config_)
|
||||
else:
|
||||
return OPTIMIZER_WRAPPERS.get_module(mod_type)(optimizer, **config_)
|
||||
config_['dataset'] = dataset
|
||||
return build_from_registry(config_, DATA_SAMPLERS)
|
||||
|
||||
|
||||
def build_lr_scheduler(config, optimizer):
|
||||
@@ -241,8 +208,8 @@ def build_lr_scheduler(config, optimizer):
|
||||
:rtype: :class:`torch.optim.lr_scheduler`
|
||||
"""
|
||||
config_ = config.copy()
|
||||
mod_type = config_.pop('type')
|
||||
return LR_SCHEDULERS.get_module(mod_type)(optimizer, **config_)
|
||||
config_['optimizer'] = optimizer
|
||||
return build_from_registry(config_, LR_SCHEDULERS)
|
||||
|
||||
|
||||
def build_schedule(config):
|
||||
|
@@ -4,7 +4,7 @@ import heapq
|
||||
from colossalai.builder import build_model, build_layer
|
||||
from colossalai.context.parallel_mode import ParallelMode
|
||||
from colossalai.core import global_context as gpc
|
||||
from colossalai.logging import get_global_dist_logger
|
||||
from colossalai.logging import get_dist_logger
|
||||
from colossalai.utils import set_to_cuda
|
||||
|
||||
|
||||
@@ -111,21 +111,21 @@ def _binary_search(weights, num):
|
||||
return intervals
|
||||
|
||||
|
||||
def _partition_uniform(num_items, num_parts, num_chunks):
|
||||
def _partition_uniform(num_items, pipeline_parallel_size, num_chunks):
|
||||
assert num_items % num_chunks == 0, \
|
||||
"Layer length should be divided by the number of chunks, otherwise parameter method is recomended"
|
||||
|
||||
logger = get_global_dist_logger()
|
||||
parts = [[] for _ in range(num_parts)]
|
||||
logger = get_dist_logger()
|
||||
parts = [[] for _ in range(pipeline_parallel_size)]
|
||||
partition_items = num_items // num_chunks
|
||||
for idx in range(num_chunks):
|
||||
base_idx = idx * partition_items
|
||||
chunk_size = partition_items // num_parts
|
||||
left = num_parts - partition_items % num_parts
|
||||
chunk_size = partition_items // pipeline_parallel_size
|
||||
left = pipeline_parallel_size - partition_items % pipeline_parallel_size
|
||||
if chunk_size == 0:
|
||||
logger.warning("Some nodes in Pipeline have no requests")
|
||||
|
||||
for p in range(num_parts):
|
||||
for p in range(pipeline_parallel_size):
|
||||
st = base_idx
|
||||
base_idx += chunk_size + (p >= left)
|
||||
parts[p].append((st, base_idx))
|
||||
@@ -133,34 +133,34 @@ def _partition_uniform(num_items, num_parts, num_chunks):
|
||||
return parts
|
||||
|
||||
|
||||
def _partition_balanced(weights, num_parts, num_chunks):
|
||||
num_total = num_parts * num_chunks
|
||||
def _partition_balanced(weights, pipeline_parallel_size, num_chunks):
|
||||
num_total = pipeline_parallel_size * num_chunks
|
||||
num_items = len(weights)
|
||||
if num_items <= num_total:
|
||||
return _partition_uniform(num_items, num_parts, num_chunks)
|
||||
return _partition_uniform(num_items, pipeline_parallel_size, num_chunks)
|
||||
|
||||
intervals = _binary_search(weights, num_total)
|
||||
|
||||
current = 0
|
||||
parts = [[] for _ in range(num_parts)]
|
||||
parts = [[] for _ in range(pipeline_parallel_size)]
|
||||
for inter in intervals:
|
||||
parts[current].append(inter)
|
||||
current = (current + 1) % num_parts
|
||||
current = (current + 1) % pipeline_parallel_size
|
||||
|
||||
return parts
|
||||
|
||||
|
||||
class ModelInitializer():
|
||||
class PipelineModelInitializer():
|
||||
def __init__(self, config, num_chunks, verbose=False):
|
||||
self.num_chunks = num_chunks
|
||||
self.ori_model = build_model(config)
|
||||
self.layers = self.ori_model.layers_cfg
|
||||
layer_length = len(self.layers)
|
||||
self.verbose = verbose
|
||||
self._logger = get_global_dist_logger()
|
||||
self._logger = get_dist_logger()
|
||||
self._logger.info(f"The total length of layers is {layer_length}", ranks=[0])
|
||||
|
||||
def model_initialize(self, partition_method='parameter'):
|
||||
def initialize(self, partition_method='parameter'):
|
||||
# Some space for initializing comunication groups
|
||||
self._interval = None
|
||||
self._partition_layers(method=partition_method)
|
||||
@@ -198,7 +198,7 @@ class ModelInitializer():
|
||||
for st, ed in self.parts[stage]:
|
||||
for idx, layer in enumerate(self.layers[st: ed]):
|
||||
log_str += f'\t{idx + st:2d}: {layer}\n'
|
||||
self._logger.info(log_str)
|
||||
self._logger.info(log_str, ranks=[0])
|
||||
|
||||
# Save the partition
|
||||
self._interval = self.parts[pipeline_rank]
|
||||
|
Reference in New Issue
Block a user