[doc] fixed compatiblity with docusaurus (#2657)

This commit is contained in:
Frank Lee
2023-02-09 17:06:29 +08:00
committed by GitHub
parent a4ae43f071
commit cd4f02bed8
42 changed files with 2 additions and 2 deletions

View File

@@ -0,0 +1,98 @@
# ColoTensor Concepts
Author: [Jiarui Fang](https://github.com/feifeibear), [Hongxin Liu](https://github.com/ver217) and [Haichen Huang](https://github.com/1SAA)
**Prerequisite:**
- [Colossal-AI Overview](../concepts/colossalai_overview.md)
- [Distributed Training](../concepts/distributed_training.md)
- [Paradigms of Parallelism](../concepts/paradigms_of_parallelism.md)
## Introduction
在ColossalAI 0.1.8 版本之后,[ColoTensor](https://colossalai.readthedocs.io/en/latest/colossalai/colossalai.tensor.html#colossalai.tensor.ColoTensor) 成为 ColossalAI 中张量的基本数据结构。 它是 torch.Tensor 的子类,可以当做 PyTorch Tensor使用。 此外一些独特的功能使其能够表示一个payload分布在多个 GPU 设备上的Global Tensor并提供一些列方式操作这个Global Tensor。 在 ColoTensor 的帮助下,用户可以以类似编写串行程序方式,编写的分布式 DNN 训练程序。
ColoTensor 包含额外的属性[ColoTensorSpec](https://colossalai.readthedocs.io/en/latest/colossalai/colossalai.tensor.tensor_spec.html#colossalai.tensor.tensor_spec.ColoTensorSpec)
来描述张量的payload分布和计算模式。
- ProcessGroup如何将进程组织为通信组。
- Distributed Spec张量如何在进程组之间分布。
- Compute Spec计算过程中如何使用张量。
我们一一详述。
## ProcessGroup
[ProcessGroup](https://colossalai.readthedocs.io/en/latest/colossalai/colossalai.tensor.html#colossalai.tensor.ProcessGroup) 类的一个实例描述了如何在进程组中组织进程。进程组内的进程可以一起参与同一个集合通信比如allgather, allreduce等。进程组组织方式被张量的并行策略支配。比如如果用户定义了Tensor的张量并行TP数据并行DP方式那么进程组的进程组织方式将被自动推导出来。 进程组设置可能因不同的张量而异。 因此,它使我们能够支持更复杂的混合并行。流水线并行(PP)定义不在ProcessGroup中描述它需要另一套机制我们将在未来补充ColoTensor应用于PP的相关内容。
目前ColoTensor 的一个进程组由 tp_degree 和 dp_degree 两种配置定义。 在 DP+TP 混合并行的情况下,可以将设备视为 2D 网格。 我们将 TP 通信组放置在设备网格的前导低维上,然后将数据并行组放置在设备网格的高维上。 原因是张量并行比数据并行具有更大的通信开销。 相邻设备放置在一个 TP 进程组内,并且通常放置在同一个节点中。
考虑到8个进程配置为tp_degree=4dp_degree=2布局如下图。 进程组 tp0 包含 gpu 0,1,2,3。 进程 dp1 包含 gpu 1 和 5。
<figure style={{textAlign: "center"}}>
<img src="https://raw.githubusercontent.com/hpcaitech/public_assets/main/colossalai/img/ColoTensor_layout_demo.PNG"/>
<figcaption>Process Group using tp_degree=4, dp_degree=2</figcaption>
</figure>
## Distributed Spec
[Distributed Spec](https://colossalai.readthedocs.io/en/latest/colossalai/colossalai.tensor.distspec.html)描述了 ColoTensor 如何在 ProcessGroup 中分布。
张量在 DP 进程组之间的分布方式是自动导出的,不需要用户手动指定。 如果这个张量是一个模型参数,它会在 DP 进程组中被复制。 如果是activation张量则沿tensor最高维度在DP进程组中进行平均分割。
因此,在使用 Distributed Spec 时,我们只需要描述张量在 TP 进程组之间的分布方式即可。 TP 进程组目前有两种分布式规范,即 [ShardSpec](https://colossalai.readthedocs.io/en/latest/colossalai/colossalai.tensor.distspec.html#colossalai.tensor.distspec.ShardSpec)和[ReplicaSpec](https://colossalai.readthedocs.io/en/latest/colossalai/colossalai.tensor.distspec.html#colossalai.tensor.distspec.ReplicaSpec)。 ShardSpec 需要指定分区的维度索引 dim 和分区个数 num_partitions。 目前我们仅支持在单个dim上进行拆分。 TP进程组上不同的dist spec可以通过set_dist_spec()接口相互转换。这些转化操作可以被记录在PyTorch的自动求导机制中并在反向传播时候触发对应的反向操作。
## Compute Spec
[ComputeSpec](https://colossalai.readthedocs.io/en/latest/colossalai/colossalai.tensor.compute_spec.html#colossalai.tensor.compute_spec.ComputeSpec)类描述Tensor如何参与计算。目前我们将作为module parameter的ColoTensor设置正确的Compute Pattern。可以触发正取的计算模式。具体应用方式我们会在接下来的文档中展示。
## ColoParameter
[ColoParameter](https://colossalai.readthedocs.io/en/latest/colossalai/colossalai.tensor.colo_parameter.html#colossalai.tensor.colo_parameter.ColoParameter)是ColoTensor的子类。用来声明Parameter。他和ColoTensor关系和Torch.Tensor和torch.Parameter一致。后者可以让tensor出现在module的parameters()和name_parameters() 的返回值中。
## Example
让我们看一个例子。 使用 tp_degree=4, dp_dgree=2 在 8 个 GPU 上初始化并Shard一个ColoTensor。 然后tensor被沿着 TP 进程组中的最后一个维度进行分片。 最后,我们沿着 TP 进程组中的第一个维度dim 0对其进行重新Shard。 我们鼓励用户运行代码并观察每个张量的形状。
```python
import torch
import torch.multiprocessing as mp
from colossalai.utils import free_port, print_rank_0
from functools import partial
import colossalai
from colossalai.tensor import ProcessGroup, ColoTensor, ColoTensorSpec, ShardSpec, ComputeSpec, ComputePattern
from colossalai.utils import free_port
import torch
def run_dist_tests(rank, world_size, port):
colossalai.launch(config={}, rank=rank, world_size=world_size, host='localhost', port=port, backend='nccl')
pg = ProcessGroup(tp_degree=2, dp_degree=2)
torch.manual_seed(0)
local_tensor = torch.randn(2, 3, 1).cuda()
print_rank_0(f"shape {local_tensor.shape}, {local_tensor.data}")
spec = ColoTensorSpec(pg, ShardSpec(dims=[-1], num_partitions=[pg.tp_world_size()]), ComputeSpec(ComputePattern.TP1D))
t1 = ColoTensor.from_torch_tensor(local_tensor, spec)
t1 = t1.to_replicate()
print_rank_0(f"shape {t1.shape}, {t1.data}")
spec2 = ShardSpec([0], [pg.tp_world_size()])
t1.set_dist_spec(spec2)
print_rank_0(f"shape {t1.shape}, {t1.data}")
def test_dist_cases(world_size):
run_func = partial(run_dist_tests, world_size=world_size, port=free_port())
mp.spawn(run_func, nprocs=world_size)
if __name__ == '__main__':
test_dist_cases(4)
```
:::caution
The ColoTensor is an experimental feature and may be updated.
:::

View File

@@ -0,0 +1,47 @@
# 命令行工具
作者: Shenggui Li
**预备知识:**
- [Distributed Training](../concepts/distributed_training.md)
- [Colossal-AI Overview](../concepts/colossalai_overview.md)
## 简介
Colossal-AI给用户提供了命令行工具目前命令行工具可以用来支持以下功能。
- 检查Colossal-AI是否安装正确
- 启动分布式训练
- 张量并行基准测试
## 安装检查
用户可以使用`colossalai check -i`这个命令来检查目前环境里的版本兼容性以及CUDA Extension的状态。
<figure style={{textAlign: "center"}}>
<img src="https://s2.loli.net/2022/05/04/KJmcVknyPHpBofa.png"/>
<figcaption>Check Installation Demo</figcaption>
</figure>
## 启动分布式训练
在分布式训练时,我们可以使用`colossalai run`来启动单节点或者多节点的多进程,详细的内容可以参考[启动 Colossal-AI](./launch_colossalai.md)。
## 张量并行基准测试
Colossal-AI提供了多种张量并行想要充分理解这些方法需要一定的学习成本对于新手来说很难靠经验选择一个并行方式。
所以我们提供了一个简单的基准测试能够让用户在自己的机器上测试不同张量并行的性能。这个基准测试跑一个并行的MLP模型
输入数据的维度为`(批大小,序列长度,隐藏层维度)`。通过指定GPU的数量Colossal-AI会搜索所有可行的并行配置。用户可以通过查看`colossalai benchmark --help`来自定义相关的测试参数。
```shell
# 使用4个GPU
colossalai benchmark --gpus 4
# 使用8个GPU
colossalai benchmark --gpus 8
```
:::caution
目前仅支持单节点的基准测试。
:::

View File

@@ -0,0 +1,136 @@
# 并行配置
作者: Shenggui Li, Siqi Mai
**预备知识:**
- [分布式训练](../concepts/distributed_training.md)
- [并行技术](../concepts/paradigms_of_parallelism.md)
- [构建配置文件](./define_your_config.md)
## 简介
我们在 Colossal-AI 中支持多种并行技术。代码库中的混合并行是指您可以轻松地结合数据并行、流水线并行和张量并行1D、2D、2.5D、3D的优势共同来进行并行训练。
每种并行方式需要不同的网络拓扑结构,因此要初始化不同的进程组。您可以通过在配置文件中设置 `parallel` 来初始化相应的进程组。 `parallel` 的配置必须遵从以下格式。数据并行度的大小将被根据您对流水线并行和张量并行的输入自动推断。`colossalai.launch` 将根据您的配置自动初始化这些分布式进程组。
我们为您提供了一些配置的例子以供参考。
```python
# sampler format
parallel = dict(
pipeline=dict("size": int),
tensor=dict("size": int, "mode": '1d' or '2d' or '2.5d' or '3d', "kwargs": Any)
)
# this is ok
parallel = dict(
pipeline=dict(size=2),
tensor=dict(size=4, mode='2d')
)
# this is ok
parallel = dict(
pipeline=2,
tensor=dict(size=4, mode='2d')
)
# this is not ok
# as you need to specify the mode for tensor parallelism
parallel = dict(
pipeline=2,
tensor=4
)
# this is ok as well as tensor will be default to size 1
# and mode None
parallel = dict(
pipeline=2
)
# this is ok as well as pipeline will default to size 1
parallel = dict(
tensor=dict(size=4, mode='2d')
)
```
关键字 `size` 指的是并行维度的并行大小。 例如流水线大小为2意味着有
将有2个流水线阶段。张量并行配置中的关键字 `mode` 意味着相应的张量并行技术
将被初始化如1D、2D、2.5D、3D。
**您也可以选择不在您的配置中使用 "并行"此时流水线和张量的并行度都将默认为大小1。**
**GPU的总数量必须等于` 数据并行大小 x 张量并行大小 x 流水线并行大小` 。**
## 数据并行
数据并行是最常见的分布式训练方式。它将数据分割成几个碎片分别在每个设备上进行训练。数据并行的配置会自动检测并为您设置。您不需要在您的配置中明确地设置它们。在Colossal-AI 中,有两种方法来处理数据并行的 all-reduce。
1. 如果您设置了梯度handler梯度handler将会all-reduce梯度。
2. 若没有指定相应的配置Colossal-AI 将会使用 PyTorch 的 DistributedDataParallel。
在大多数情况下,若您对梯度没有复杂的处理的需求,您将会使用第二种模式。
## 1D, 2D, 2.5D 和 3D 并行
为了实现混合并行,我们提供了一系列张量并行方法。您可以阅读相应的学术论文进行深入的了解。这些并行模式需要和 Colossal-AI 提供的分布式层一同工作。
- 1D: [Megatron-LM: Training Multi-Billion Parameter Language Models Using Model Parallelism](https://arxiv.org/abs/1909.08053)
- 2D: [An Efficient 2D Method for Training Super-Large Deep Learning Models](https://arxiv.org/abs/2104.05343)
2D 并行基于 SUMMA 矩阵乘法,它将输入数据、模型权重和层输出切分成两个不同的维度。 这些张量块分布在 `P = N^2` 设备的二维网格上,其中 `N` 是单一维度上张量块的数量。
- 2.5D: [2.5-dimensional distributed model training](https://arxiv.org/abs/2105.14500)
在 2.5D 矩阵乘法的启发下2.5D 并行引入了一种新的张量并行进一步将2D张量并行化。其中`P = N^2 d` 个处理器被分配到 `d` 层, 每层独立进行矩阵乘法运算,维度为 `N`
- 3D: [Maximizing Parallelism in Distributed Training for Huge Neural Networks](https://arxiv.org/abs/2105.14450)
我们还介绍了一种 3D 张量并行方法,在三维处理器立方体上并行化神经网络。这种方法在数量为 `P` 的处理器上实现了最佳的 `O(P^{1/3})` 通信开销,而计算和内存的使用都是通过优化的参数和激活的负载平衡来实现的。同时,通过优化参数和 activations 的负载平衡,计算和内存的使用都是均匀分布的。
```python
# 1D parallel
parallel = dict(
tensor=dict(size=4, mode='1d')
)
# 2D parallel
parallel = dict(
tensor=dict(size=4, mode='2d')
)
# 2.5D parallel
parallel = dict(
tensor=dict(size=8, mode='2.5d', depth=2)
)
# 3D parallel
parallel = dict(
tensor=dict(size=8, mode='3d')
)
```
当您在配置中指定了张量并行模式,您就可以使用其相应的分布式算子。例如,若您设置模式为 `2d`,那么在模型构建中就能使用 `colossalai.nn.Linear2D` 了。
## 流水线并行
流水线并行是将模型按层分成几个部分。例如,假设我们有一个简单的模型,它由两个线性层组成。我们有两个 GPU我们可以将第一个线性层分配给第一个 GPU 而第二层则分配给第二个 GPU。
您可以在您的配置文件中设置流水线并行度的大小。当流水线并行度大于1Colossal-AI 将会自动地创建流水线并行的 schedule这将会为您定义好模型训练的 `forward``backward`
```python
parallel = dict(
pipeline=dict(size=4), # number of pipeline stages
)
```
## 序列并行
针对处理大图片、视频、长文本、长时间医疗监控等数据的需要Colossal-AI 还提供了序列并行的方法。该方法是在论文[Sequence Parallelism: Making 4D Parallelism Possible](https://arxiv.org/abs/2105.13120)中提出的。您可以指定模式为 `sequence` 来初始化进程组。
```python
parallel = dict(
tensor=dict(size=4, mode='sequence')
)
```

View File

@@ -0,0 +1,71 @@
# 构建配置文件
作者: Guangyang Lu, Shenggui Li, Siqi Mai
**预备知识:**
- [分布式训练](../concepts/distributed_training.md)
- [Colossal-AI 总览](../concepts/colossalai_overview.md)
## 简介
在 Colossal-AI 中,我们需要一个配置文件来指定系统在训练过程中要注入的特征。在本教程中,我们将向您介绍如何构建您的配置文件以及如何使用这个配置文件。使用配置文件有以下一些好处:
1. 您可以在不同的配置文件中存储您的特征配置和训练超参数。
2. 对于我们未来发布的新功能,您亦可以在配置中指定,而无需改变训练脚本的代码。
在本教程中,我们将向您介绍如何构建您的配置文件。
## 配置定义
在一个配置文件中,有两种类型的变量。一种是作为特征说明,另一种是作为超参数。所有与特征相关的变量都是保留关键字。例如,如果您想使用混合精度训练,需要在 config 文件中使用变量名`fp16`,并遵循预先定义的格式。
### 功能配置
Colossal-AI 提供了一系列的功能来加快训练速度。每个功能都是由配置文件中的相应字段定义的。在本教程中,我们不会给出所有功能的配置细节,而是提供一个如何指定一个功能的说明。**每个功能的细节可以在其各自的教程中找到。**
为了说明配置文件的使用,我们在这里使用混合精度训练作为例子。您需要遵循以下步骤。
1. 创建一个配置文件(例如 `config.py`,您可以指定任意的文件名)。
2. 在配置文件中定义混合精度的配置。例如,为了使用 PyTorch 提供的原始混合精度训练,您只需将下面这几行代码写入您的配置文件中。
```python
from colossalai.amp import AMP_TYPE
fp16 = dict(
mode=AMP_TYPE.TORCH
)
```
3. 当启动分布式环境时,向 Colossal-AI 指定您的配置文件的位置。比如下面的例子是配置文件在当前目录下。
```python
import colossalai
colossalai.launch(config='./config.py', ...)
```
这样Colossal-AI 便知道您想使用什么功能,并会在 `colossalai.initialize` 期间注入您所需要的功能。
### 全局超参数
除了功能的配置,您还可以在配置文件中定义训练的超参数。当您想进行多个实验时,这将会变得非常方便。每个实验的细节都可以放在独立的配置文件中,以避免混乱。这些参数将被存储在全局并行环境中,可以在训练脚本中访问。
例如,您可以在配置文件中指定批量大小。
```python
BATCH_SIZE = 32
```
启动后,您能够通过全局并行上下文访问您的超参数。
```python
import colossalai
from colossalai.core import global_context as gpc
colossalai.launch(config='./config.py', ...)
# access your parameter
print(gpc.config.BATCH_SIZE)
```

View File

@@ -0,0 +1,384 @@
# 如何在训练中使用 Engine 和 Trainer
作者: Shenggui Li, Siqi Mai
**预备知识:**
- [初始化功能](./initialize_features.md)
## 简介
在本教程中,您将学习如何使用 Colossal-AI 中提供的 Engine 和 Trainer 来训练您的模型。在深入研究细节之前,我们想先解释一下 Engine 和 Trainer 的概念。
### Engine
Engine 本质上是一个模型、优化器和损失函数的封装类。当我们调用 `colossalai.initialize` 时,一个 Engine 对象将被返回,并且配备了在您的配置文件中指定的梯度剪裁、梯度累计和 ZeRO 优化器等功能。
Engine 将使用与 PyTorch 训练组件类似的 API因此您只需对代码进行微小的修改即可。
下表展示了Engine的常用API。
| 组件 | 功能 | PyTorch | Colossal-AI |
| ------------------------------------- | --------------------------------------------- | ------------------------------- | -------------------------------------- |
| optimizer | 迭代前将所有梯度设置为零 | optimizer.zero_grad() | engine.zero_grad() |
| optimizer | 更新参数 | optimizer.step() | engine.step() |
| model | 进行一次前向计算 | outputs = model(inputs) | outputs = engine(inputs) |
| criterion | 计算loss值 | loss = criterion(output, label) | loss = engine.criterion(output, label) |
| criterion | 反向计算 | loss.backward() | engine.backward(loss) |
我们需要这样一个 Engine 类的原因是,我们可以添加更多的功能,同时将实现隐藏在
`colossalai.initialize` 函数中实现。
假如我们要添加一个新的功能,我们可以在 `colossalai.initialize` 函数中完成对于模型、优化器、数据加载器和损失函数的功能诠释。不管中间的过程有多复杂,最终我们呈现的以及用户需要使用的只有一个 Engine 类,这将十分便捷。
用户只需要在最小范围内修改他们的代码,将普通的 PyTorch APIs 调整为 Colossal-AI
Engine 的 API。通过这种方式他们可以享受更多的功能来进行有效的训练。
以下是一个简单的例子:
```python
import colossalai
# build your model, optimizer, criterion, dataloaders
...
engine, train_dataloader, test_dataloader, _ = colossalai.initialize(model,
optimizer,
criterion,
train_dataloader,
test_dataloader)
for img, label in train_dataloader:
engine.zero_grad()
output = engine(img)
loss = engine.criterion(output, label)
engine.backward(loss)
engine.step()
```
### Trainer
Trainer 是一个更高级的封装器,用户可以用更少的代码行来执行训练。 由于 Trainer 的使用会更加简单,相较于 Engine它会缺少一点灵活性。 Trainer 被设计为进行前向和反向计算来进行模型权重的更新。通过传递 Engine 对象,我们可以很容易地创建一个 Trainer。
Trainer 的参数 `schedule` 默认值是 `None` 。在大多数情况下,除非我们想使用流水线并行,否则我们把这个值设为 `None`。如果您想探索更多关于这个参数的内容,您可以前往流水线并行的相关教程。
```python
from colossalai.logging import get_dist_logger
from colossalai.trainer import Trainer, hooks
# build components and initialize with colossalai.initialize
...
# create a logger so that trainer can log on the console
logger = get_dist_logger()
# create a trainer object
trainer = Trainer(
engine=engine,
logger=logger
)
```
在 Trainer 中,用户可以定制一些 hooks并将这些 hooks 附加到 Trainer 上。hook 将根据训练方案定期地执行生命周期函数。例如,基于用户是想在每次训练迭代后还是只在整个训练周期后更新学习率,
`LRSchedulerHook` 将会在 `after_train_iter``after_train_epoch` 阶段执行 `lr_scheduler.step()` 去为用户更新学习率。您可以将 hook 存储在一个列表中并将其传递给 `trainer.fit` 方法。`trainer.fit` 方法将根据您的参数执行训练和测试。如果 `display_process` 为 True将在您的控制台显示一个进度条以显示训练的过程。
```python
# define the hooks to attach to the trainer
hook_list = [
hooks.LossHook(),
hooks.LRSchedulerHook(lr_scheduler=lr_scheduler, by_epoch=True),
hooks.AccuracyHook(accuracy_func=Accuracy()),
hooks.LogMetricByEpochHook(logger),
]
# start training
trainer.fit(
train_dataloader=train_dataloader,
epochs=NUM_EPOCHS,
test_dataloader=test_dataloader,
test_interval=1,
hooks=hook_list,
display_progress=True
)
```
如果您想定制您的 hook 类,您可以继承 `hooks.BaseHook` 并重写您想要的生命周期方法。下面提供了一个例子来演示如何创建一个简单的关于日志信息的 hook以供您参考。
```python
from colossalai.logging import get_dist_logger
from colossalai.trainer import hooks
class LogMessageHook(hooks.BaseHook):
def __init__(self, priority=10):
self._logger = get_dist_logger()
def before_train(self, trainer):
self._logger.info('training starts')
def after_train(self, trainer):
self._logger.info('training finished')
...
# then in your training script
hook_list.append(LogMessageHook())
```
在下面的章节中,您将会详细地了解到如何用 Engine 和 Trainer 来训练 ResNet 模型。
## ResNet
### 总览
在本节中,我们将介绍:
1. 使用一个 Engine 在 CIFAR10 数据集上训练 ResNet34 模型
2. 使用一个 Trainer 在 CIFAR10 数据集上训练 ResNet34 模型
项目结构如下:
```bash
-- config.py
-- run_resnet_cifar10_with_engine.py
-- run_resnet_cifar10_with_trainer.py
```
对于使用 Engine 或 Trainer步骤 1-4 是通用的。 因此,步骤 1-4 + 步骤 5 将会是对应 `run_resnet_cifar10_with_engine.py` 而 步骤 1-4 + 步骤6 则对应 `run_resnet_cifar10_with_trainer.py`
### 牛刀小试
#### 步骤 1. 创建配置文件
在你的项目文件夹中,创建一个 `config.py`。这个文件是用来指定一些您可能想用来训练您的模型的特征。下面是一个配置文件的例子。
```python
from colossalai.amp import AMP_TYPE
BATCH_SIZE = 128
NUM_EPOCHS = 200
fp16=dict(
mode=AMP_TYPE.TORCH
)
```
在这个配置文件中,我们指定要在每个 GPU 上使用批大小为128并运行200个 epoch。这两个参数是在 `gpc.config` 中体现的。例如,您可以使用 `gpc.config.BATCH_SIZE` 来访问您存储在配置文件中的批大小值。而 `fp16` 配置则会告诉 `colossalai.initialize` 使用 PyTorch 提供的混合精度训练,以更好的速度和更低的内存消耗来训练模型。
#### 步骤 2. 初始化分布式环境
我们需要初始化分布式训练环境。这在 [启动 Colossal-AI](./launch_colossalai.md) 中有相应的教程。在当前的演示中,我们使用 `launch_from_torch` 和 PyTorch 启用工具。
```python
import colossalai
# ./config.py refers to the config file we just created in step 1
colossalai.launch_from_torch(config='./config.py')
```
#### 步骤 3. 创建所有的训练组件
这时,我们可以创建用于训练的所有组件,包括:
1. 模型
2. 优化器
3. 损失函数
4. 训练/测试数据加载器
5. 学习率调度器
6. 日志记录器
为了构建这些组件,您需要导入以下模块。
```python
from pathlib import Path
from colossalai.logging import get_dist_logger
import torch
import os
from colossalai.core import global_context as gpc
from colossalai.utils import get_dataloader
from torchvision import transforms
from colossalai.nn.lr_scheduler import CosineAnnealingLR
from torchvision.datasets import CIFAR10
from torchvision.models import resnet34
```
然后按照通常在PyTorch脚本中构建组件的方式来构建组件。在下面的脚本中我们将CIFAR10数据集的根路径设置为环境变量 `DATA`。您可以把它改为您想要的任何路径,例如,您可以把 `root=Path(os.environ['DATA'])` 改为 `root='./data'` ,这样就不需要设置环境变量。
```python
# build logger
logger = get_dist_logger()
# build resnet
model = resnet34(num_classes=10)
# build datasets
train_dataset = CIFAR10(
root='./data',
download=True,
transform=transforms.Compose(
[
transforms.RandomCrop(size=32, padding=4),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize(mean=[0.4914, 0.4822, 0.4465], std=[
0.2023, 0.1994, 0.2010]),
]
)
)
test_dataset = CIFAR10(
root='./data',
train=False,
transform=transforms.Compose(
[
transforms.ToTensor(),
transforms.Normalize(mean=[0.4914, 0.4822, 0.4465], std=[
0.2023, 0.1994, 0.2010]),
]
)
)
# build dataloaders
train_dataloader = get_dataloader(dataset=train_dataset,
shuffle=True,
batch_size=gpc.config.BATCH_SIZE,
num_workers=1,
pin_memory=True,
)
test_dataloader = get_dataloader(dataset=test_dataset,
add_sampler=False,
batch_size=gpc.config.BATCH_SIZE,
num_workers=1,
pin_memory=True,
)
# build criterion
criterion = torch.nn.CrossEntropyLoss()
# optimizer
optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9, weight_decay=5e-4)
# lr_scheduler
lr_scheduler = CosineAnnealingLR(optimizer, total_steps=gpc.config.NUM_EPOCHS)
```
#### 步骤 4. 用 Colossal-AI 进行初始化
接下来,重要的一步是通过调用 `colossalai.initialize` 获得 Engine。正如 `config.py` 中所述,我们将使用混合精度训练来训练 ResNet34 模型。`colossalai.initialize` 将自动检查您的配置文件,并将相关特征分配给您的训练组件。这样一来,我们的 Engine 已经能够进行混合精度训练,而您不需要进行额外的处理。
```python
engine, train_dataloader, test_dataloader, _ = colossalai.initialize(model,
optimizer,
criterion,
train_dataloader,
test_dataloader,
)
```
#### 步骤 5. 用 Engine 进行训练
当所有的训练组件都准备好后,我们就可以像使用 PyTorch 一样训练 ResNet34 了。
```python
for epoch in range(gpc.config.NUM_EPOCHS):
# execute a training iteration
engine.train()
for img, label in train_dataloader:
img = img.cuda()
label = label.cuda()
# set gradients to zero
engine.zero_grad()
# run forward pass
output = engine(img)
# compute loss value and run backward pass
train_loss = engine.criterion(output, label)
engine.backward(train_loss)
# update parameters
engine.step()
# update learning rate
lr_scheduler.step()
# execute a testing iteration
engine.eval()
correct = 0
total = 0
for img, label in test_dataloader:
img = img.cuda()
label = label.cuda()
# run prediction without back-propagation
with torch.no_grad():
output = engine(img)
test_loss = engine.criterion(output, label)
# compute the number of correct prediction
pred = torch.argmax(output, dim=-1)
correct += torch.sum(pred == label)
total += img.size(0)
logger.info(
f"Epoch {epoch} - train loss: {train_loss:.5}, test loss: {test_loss:.5}, acc: {correct / total:.5}, lr: {lr_scheduler.get_last_lr()[0]:.5g}", ranks=[0])
```
#### 步骤 6. 用 Trainer 进行训练
如果您想用 Trainer 进行训练,您可以参考下面的代码进行您的实验。
```python
from colossalai.nn.metric import Accuracy
from colossalai.trainer import Trainer, hooks
# create a trainer object
trainer = Trainer(
engine=engine,
logger=logger
)
# define the hooks to attach to the trainer
hook_list = [
hooks.LossHook(),
hooks.LRSchedulerHook(lr_scheduler=lr_scheduler, by_epoch=True),
hooks.AccuracyHook(accuracy_func=Accuracy()),
hooks.LogMetricByEpochHook(logger),
hooks.LogMemoryByEpochHook(logger)
]
# start training
# run testing every 1 epoch
trainer.fit(
train_dataloader=train_dataloader,
epochs=gpc.config.NUM_EPOCHS,
test_dataloader=test_dataloader,
test_interval=1,
hooks=hook_list,
display_progress=True
)
```
#### 步骤 7. 开始分布式训练
最后,我们可以使用 PyTorch 提供的分布式启动器来调用脚本因为我们在步骤2中使用了 `launch_from_torch`。您需要把`<num_gpus>` 替换成您机器上可用的GPU数量。如果您只想使用一个 GPU您可以把这个数字设为1。如果您想使用其他的启动器请您参考如何启动 Colossal-AI 的教程。
```bash
# with engine
python -m torch.distributed.launch --nproc_per_node <num_gpus> --master_addr localhost --master_port 29500 run_resnet_cifar10_with_engine.py
# with trainer
python -m torch.distributed.launch --nproc_per_node <num_gpus> --master_addr localhost --master_port 29500 run_resnet_cifar10_with_trainer.py
```

View File

@@ -0,0 +1,46 @@
# 初始化功能
作者: Shenggui Li, Siqi Mai
**预备知识:**
- [分布式训练](../concepts/distributed_training.md)
- [Colossal-AI 总览](../concepts/colossalai_overview.md)
## 简介
在本教程中,我们将介绍 `colossalai.initialize` 的使用。 它包含了如何将特征(例如,模型、优化器、数据加载器)无缝注入您的训练组件中。 调用 `colossalai.initialize` 是您进入训练循环前的基本操作。
在下面一节中,我们将介绍 `colossalai.initialize` 是如何工作的以及使用中我们要注意的细节。
## 使用
在一个典型的工作流程中,我们将在训练脚本的开始启动分布式环境。
之后,我们将实例化我们的对象,如模型、优化器、损失函数、数据加载器等。此时,我们可以使用 `colossalai.initialize` 便捷地为这些对象注入特征。
具体细节请看以下的伪代码例子。
```python
import colossalai
import torch
...
# launch distributed environment
colossalai.launch(config='./config.py', ...)
# create your objects
model = MyModel()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
criterion = torch.nn.CrossEntropyLoss()
train_dataloader = MyTrainDataloader()
test_dataloader = MyTrainDataloader()
# initialize features
engine, train_dataloader, test_dataloader, _ = colossalai.initialize(model,
optimizer,
criterion,
train_dataloader,
test_dataloader)
```
`colossalai.initialize` 将返回一个 `Engine` 对象。 该对象把模型、优化器和损失函数封装起来。 **`Engine` 对象会以配置文件中指定的特征运行。**
关于 `Engine` 的更多使用细节可以在 [在训练中使用Engine和Trainer](./engine_trainer.md) 中获取。

View File

@@ -0,0 +1,212 @@
# 启动 Colossal-AI
作者: Chuanrui Wang, Shenggui Li, Siqi Mai
**预备知识:**
- [分布式训练](../concepts/distributed_training.md)
- [Colossal-AI 总览](../concepts/colossalai_overview.md)
## 简介
正如我们在前面的教程中所提到的,在您的配置文件准备好后,您需要为 Colossal-AI 初始化分布式环境。我们把这个过程称为 `launch`。在本教程中,您将学习如何在您的服务器上启动 Colossal-AI不管是小型的还是大型的。
在 Colossal-AI 中,我们提供了几种启动方法来初始化分布式后端。
在大多数情况下,您可以使用 `colossalai.launch``colossalai.get_default_parser` 来通过命令行传递参数。如果您想使用 SLURM、OpenMPI 和 PyTorch 等启动工具,我们也提供了几个启动的辅助方法以便您的使用。您可以直接从这些启动工具设置的环境变量中访问 rank 和 world size 大小。
在本教程中,我们将介绍如何启动 Colossal-AI 来初始化分布式后端:
- 用 colossalai.launch 启动
- 用 Colossal-AI命令行 启动
- 用 SLURM 启动
- 用 OpenMPI 启动
## 启动分布式环境
为了启动 Colossal-AI我们需要两类参数:
1. 配置文件
2. 分布式设置
无论我们使用何种启动方式,配置文件是必须要求的,而分布式设置有可能依情况而定。配置文件可以是配置文件的路径或 Python dictionary 的形式。分布式设置可以通过命令行或多进程启动器传递。
### 命令行解析器
在使用 `launch` 之前, 我们首先需要了解我们需要哪些参数来进行初始化。
如[分布式训练](../concepts/distributed_training.md) 中 `基本概念` 一节所述 ,涉及的重要参数是:
1. host
2. port
3. rank
4. world_size
5. backend
在 Colossal-AI 中,我们提供了一个命令行解析器,它已经提前添加了这些参数。您可以通过调用 `colossalai.get_default_parser()` 来获得这个解析器。这个解析器通常与 `colossalai.launch` 一起使用。
```python
# add these lines in your train.py
import colossalai
# get default parser
parser = colossalai.get_default_parser()
# if you want to add your own arguments
parser.add_argument(...)
# parse arguments
args = parser.parse_args()
```
您可以在您的终端传入以下这些参数。
```shell
python train.py --host <host> --rank <rank> --world_size <world_size> --port <port> --backend <backend>
```
`backend` 是用户可选的,默认值是 nccl。
### 本地启动
为了初始化分布式环境,我们提供了一个通用的 `colossalai.launch` API。`colossalai.launch` 函数接收上面列出的参数,并在通信网络中创建一个默认的进程组。方便起见,这个函数通常与默认解析器一起使用。
```python
import colossalai
# parse arguments
args = colossalai.get_default_parser().parse_args()
# launch distributed environment
colossalai.launch(config=<CONFIG>,
rank=args.rank,
world_size=args.world_size,
host=args.host,
port=args.port,
backend=args.backend
)
```
### 用 Colossal-AI命令行工具 启动
为了更好地支持单节点以及多节点的训练我们通过封装PyTorch的启动器实现了一个更加方便的启动器。
PyTorch自带的启动器需要在每个节点上都启动命令才能启动多节点训练而我们的启动器只需要一次调用即可启动训练。
首先我们需要在代码里指定我们的启动方式。由于这个启动器是PyTorch启动器的封装那么我们自然而然应该使用`colossalai.launch_from_torch`
分布式环境所需的参数,如 rank, world size, host 和 port 都是由 PyTorch 启动器设置的,可以直接从环境变量中读取。
```python
import colossalai
colossalai.launch_from_torch(
config=<CONFIG>,
)
```
接下来,我们可以轻松地在终端使用`colossalai run`来启动训练。下面的命令可以在当前机器上启动一个4卡的训练任务。
你可以通过设置`nproc_per_node`来调整使用的GPU的数量也可以改变`master_port`的参数来选择通信的端口。
```shell
# 在当前节点上启动4卡训练 默认使用29500端口
colossalai run --nproc_per_node 4 train.py
# 在当前节点上启动4卡训练并使用一个不同的端口
colossalai run --nproc_per_node 4 --master_port 29505 test.py
```
如果你在使用一个集群并且想进行多节点的训练你需要使用Colossal-AI的命令行工具进行一键启动。我们提供了两种方式来启动多节点任务
- 通过`--hosts`来启动
这个方式适合节点数不多的情况。假设我们有两个节点,分别为`host``host2`。我们可以用以下命令进行多节点训练。
比起单节点训练,多节点训练需要手动设置`--master_addr` (在单节点训练中`master_addr`默认为`127.0.0.1`)。
:::caution
多节点训练时,`master_addr`不能为`localhost`或者`127.0.0.1`它应该是一个节点的名字或者IP地址。
:::
```shell
# 在两个节点上训练
colossalai run --nproc_per_node 4 --host host1,host2 --master_addr host1 test.py
```
- 通过`--hostfile`来启动
这个方式适用于节点数很大的情况。host file是一个简单的文本文件这个文件里列出了可以使用的节点的名字。
在一个集群中可用节点的列表一般由SLURM或者PBS Pro这样的集群资源管理器来提供。比如在SLURM中
你可以从`SLURM_NODELIST`这个环境变量中获取到当前分配列表。在PBS Pro中这个环境变量为`PBS_NODEFILE`
可以通过`echo $SLURM_NODELIST` 或者 `cat $PBS_NODEFILE` 来尝试一下。如果你没有这样的集群管理器,
那么你可以自己手动写一个这样的文本文件即可。
提供给Colossal-AI的host file需要遵循以下格式每一行都是一个节点的名字。
```text
host1
host2
```
如果host file准备好了那么我们就可以用以下命令开始多节点训练了。和使用`--host`一样,你也需要指定一个`master_addr`
当使用host file时我们可以使用一些额外的参数
- `--include`: 设置你想要启动训练的节点。比如你的host file里有8个节点但是你只想用其中的6个节点进行训练
你可以添加`--include host1,host2,host3,...,host6`这样训练任务只会在这6个节点上启动。
- `--exclude`: 设置你想排除在训练之外的节点。当你的某一些节点坏掉时这个参数会比较有用。比如假如host1的GPU有一些问题无法正常使用
那么你就可以使用`--exclude host1`来将其排除在外,这样你就可以训练任务就只会在剩余的节点上启动。
```shell
# 使用hostfile启动
colossalai run --nproc_per_node 4 --hostfile ./hostfile --master_addr host1 test.py
# 只使用部分节点进行训练
colossalai run --nproc_per_node 4 --hostfile ./hostfile --master_addr host1 --include host1 test.py
# 不使用某些节点进行训练
colossalai run --nproc_per_node 4 --hostfile ./hostfile --master_addr host1 --exclude host2 test.py
```
### 用 SLURM 启动
如果您是在一个由 SLURM 调度器管理的系统上, 您也可以使用 `srun` 启动器来启动您的 Colossal-AI 脚本。我们提供了辅助函数 `launch_from_slurm` 来与 SLURM 调度器兼容。
`launch_from_slurm` 会自动从环境变量 `SLURM_PROCID``SLURM_NPROCS` 中分别读取 rank 和 world size ,并使用它们来启动分布式后端。
您可以在您的训练脚本中尝试以下操作。
```python
import colossalai
colossalai.launch_from_slurm(
config=<CONFIG>,
host=args.host,
port=args.port
)
```
您可以通过在终端使用这个命令来初始化分布式环境。
```bash
srun python train.py --host <master_node> --port 29500
```
### 用 OpenMPI 启动
如果您对OpenMPI比较熟悉您也可以使用 `launch_from_openmpi`
`launch_from_openmpi` 会自动从环境变量
`OMPI_COMM_WORLD_LOCAL_RANK` `MPI_COMM_WORLD_RANK``OMPI_COMM_WORLD_SIZE` 中分别读取local rank、global rank 和 world size并利用它们来启动分布式后端。
您可以在您的训练脚本中尝试以下操作。
```python
colossalai.launch_from_openmpi(
config=<CONFIG>,
host=args.host,
port=args.port
)
```
以下是用 OpenMPI 启动多个进程的示例命令。
```bash
mpirun --hostfile <my_hostfile> -np <num_process> python train.py --host <node name or ip> --port 29500
```
- --hostfile: 指定一个要运行的主机列表。
- --np: 设置总共要启动的进程GPU的数量。例如如果 --np 44个 python 进程将被初始化以运行 train.py。

View File

@@ -0,0 +1,61 @@
# 模型检查点
作者 : Guangyang Lu
**预备知识:**
- [Launch Colossal-AI](./launch_colossalai.md)
- [Initialize Colossal-AI](./initialize_features.md)
**示例代码:**
- [ColossalAI-Examples Model Checkpoint](https://github.com/hpcaitech/ColossalAI-Examples/tree/main/utils/checkpoint)
**函数是经验函数.**
## 简介
本教程将介绍如何保存和加载模型检查点。
为了充分利用Colossal-AI的强大并行策略我们需要修改模型和张量可以直接使用 `torch.save` 或者 `torch.load` 保存或加载模型检查点。在Colossal-AI中我们提供了应用程序接口实现上述同样的效果。
但是,在加载时,你不需要使用与存储相同的保存策略。
## 使用方法
### 保存
有两种方法可以使用Colossal-AI训练模型即使用engine或使用trainer。
**注意我们只保存 `state_dict`.** 因此,在加载检查点时,需要首先定义模型。
#### 同 engine 保存
```python
from colossalai.utils import save_checkpoint
model = ...
engine, _, _, _ = colossalai.initialize(model=model, ...)
for epoch in range(num_epochs):
... # do some training
save_checkpoint('xxx.pt', epoch, model)
```
#### 用 trainer 保存
```python
from colossalai.trainer import Trainer, hooks
model = ...
engine, _, _, _ = colossalai.initialize(model=model, ...)
trainer = Trainer(engine, ...)
hook_list = [
hooks.SaveCheckpointHook(1, 'xxx.pt', model)
...]
trainer.fit(...
hook=hook_list)
```
### 加载
```python
from colossalai.utils import load_checkpoint
model = ...
load_checkpoint('xxx.pt', model)
... # train or test
```