mirror of
https://github.com/hpcaitech/ColossalAI.git
synced 2025-09-22 01:48:07 +00:00
[doc] clean up outdated docs (#4765)
* [doc] clean up outdated docs * [doc] fix linking * [doc] fix linking
This commit is contained in:
@@ -1,99 +0,0 @@
|
||||
# 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=4,dp_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_degree=2 在 8 个 GPU 上初始化并Shard一个ColoTensor。 然后tensor被沿着 TP 进程组中的最后一个维度进行分片。 最后,我们沿着 TP 进程组中的第一个维度(dim 0)对其进行重新Shard。 我们鼓励用户运行代码并观察每个张量的形状。
|
||||
|
||||
|
||||
```python
|
||||
import torch
|
||||
import torch.multiprocessing as mp
|
||||
from colossalai.utils import print_rank_0
|
||||
from functools import partial
|
||||
|
||||
import colossalai
|
||||
from colossalai.tensor import ProcessGroup, ColoTensor, ColoTensorSpec, ShardSpec, ComputeSpec, ComputePattern
|
||||
from colossalai.testing import spawn
|
||||
|
||||
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):
|
||||
spawn(run_dist_tests, world_size)
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_dist_cases(4)
|
||||
```
|
||||
|
||||
:::caution
|
||||
|
||||
The ColoTensor is an experimental feature and may be updated.
|
||||
|
||||
:::
|
@@ -1,138 +0,0 @@
|
||||
# 并行配置
|
||||
|
||||
作者: Shenggui Li, Siqi Mai
|
||||
|
||||
> ⚠️ 此页面上的信息已经过时并将被废弃。请在[Booster插件](../basics/booster_plugins.md)页面查阅更新。
|
||||
|
||||
**预备知识:**
|
||||
- [分布式训练](../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。
|
||||
|
||||
您可以在您的配置文件中设置流水线并行度的大小。当流水线并行度大于1,Colossal-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')
|
||||
)
|
||||
```
|
@@ -1,73 +0,0 @@
|
||||
# 构建配置文件
|
||||
|
||||
作者: Guangyang Lu, Shenggui Li, Siqi Mai
|
||||
|
||||
> ⚠️ 此页面上的信息已经过时并将被废弃。请在[Booster API](../basics/booster_api.md)页面查阅更新。
|
||||
|
||||
**预备知识:**
|
||||
- [分布式训练](../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)
|
||||
|
||||
```
|
@@ -1,387 +0,0 @@
|
||||
# 如何在训练中使用 Engine 和 Trainer
|
||||
|
||||
作者: Shenggui Li, Siqi Mai
|
||||
|
||||
> ⚠️ 此页面上的信息已经过时并将被废弃。请在[Booster API](../basics/booster_api.md)页面查阅更新。
|
||||
|
||||
**预备知识:**
|
||||
- [初始化功能](./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.legacy.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.legacy.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.legacy.nn.metric import Accuracy
|
||||
from colossalai.legacy.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
|
||||
```
|
||||
<!-- doc-test-command: echo -->
|
@@ -1,48 +0,0 @@
|
||||
# 初始化功能
|
||||
|
||||
作者: Shenggui Li, Siqi Mai
|
||||
|
||||
> ⚠️ 此页面上的信息已经过时并将被废弃。请在[Booster API](../basics/booster_api.md)页面查阅更新。
|
||||
|
||||
**预备知识:**
|
||||
- [分布式训练](../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) 中获取。
|
@@ -1,64 +0,0 @@
|
||||
# 模型Checkpoint
|
||||
|
||||
作者 : Guangyang Lu
|
||||
|
||||
> ⚠️ 此页面上的信息已经过时并将被废弃。请在[Booster Checkpoint](../basics/booster_checkpoint.md)页面查阅更新。
|
||||
|
||||
**预备知识:**
|
||||
- [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)
|
||||
|
||||
**函数是经验函数.**
|
||||
|
||||
## 简介
|
||||
|
||||
本教程将介绍如何保存和加载模型Checkpoint。
|
||||
|
||||
为了充分利用Colossal-AI的强大并行策略,我们需要修改模型和张量,可以直接使用 `torch.save` 或者 `torch.load` 保存或加载模型Checkpoint。在Colossal-AI中,我们提供了应用程序接口实现上述同样的效果。
|
||||
|
||||
但是,在加载时,你不需要使用与存储相同的保存策略。
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 保存
|
||||
|
||||
有两种方法可以使用Colossal-AI训练模型,即使用engine或使用trainer。
|
||||
**注意我们只保存 `state_dict`.** 因此,在加载Checkpoint时,需要首先定义模型。
|
||||
|
||||
#### 同 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.legacy.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
|
||||
```
|
||||
<!-- doc-test-command: echo -->
|
Reference in New Issue
Block a user