# 内容
   * [内容](#内容)
   * [环境配置](#环境配置)
   * [下载词汇文件](#下载词汇文件)
   * [下载训练数据](#下载训练数据)
   * [训练](#训练)
      * [数据预处理](#数据预处理)
      * [GPT预训练](#GPT预训练)
         * [单卡训练](#单卡训练)
         * [Deepspeed-PP和ZeRO-DP](#Deepspeed-PP和ZeRO-DP)
         * [分布式多卡训练](#分布式多卡训练)
   * [推理](#推理)
      * [模型转换](#模型转换)
      * [GPT文本生成](#GPT文本生成)
   * [参考](#参考)

# 环境配置
1. 安装基础依赖包

pip install -r requirements.txt

2. 安装DCU相关whl包
DCU相关包下载目录：[https://cancon.hpccube.com:65024/4/main](https://cancon.hpccube.com:65024/4/main)

pytorch whl包：pytorch ---> dtk-23.04
根据python版本,下载对应pytorch的whl包
<pre>
pip install torch* (下载的torch的whl包)
</pre>

torchvision whl包：vision ---> dtk-23.04
根据python版本,下载对应torchvision的whl包
<pre>
pip install torchvision* (下载的torchvision的whl包)
</pre>

apex whl包：apex ---> dtk-23.04
根据python版本,下载对应apex的whl包
<pre>
pip install apex* (下载的apex的whl包)
</pre>

deepspeed whl包：deepspeed ---> dtk-23.04
根据python版本,下载对应apex的whl包
<pre>
pip install deepspeed* (下载的apex的whl包)
</pre>

若使用 pip install 下载安装过慢，可添加源：-i https://pypi.tuna.tsinghua.edu.cn/simple/

# 下载词汇文件

<pre>
wget https://s3.amazonaws.com/models.huggingface.co/bert/gpt2-vocab.json
wget https://s3.amazonaws.com/models.huggingface.co/bert/gpt2-merges.txt
</pre>


# 下载训练数据
使用1GB 79K jsonl数据集
<pre>
wget https://huggingface.co/bigscience/misc-test-data/resolve/main/stas/oscar-1GB.jsonl.xz
xz -d oscar-1GB.jsonl.xz
</pre>

# 训练

## 数据预处理

<pre>
python tools/preprocess_data.py \
    --input oscar-1GB.jsonl \
    --output-prefix my-gpt2 \
    --vocab gpt2-vocab.json \
    --dataset-impl mmap \
    --tokenizer-type GPT2BPETokenizer \
    --merge-file gpt2-merges.txt \
    --append-eod \
    --workers 8
</pre>

## GPT预训练

### 单卡训练
1. `examples/pretrain_gpt.sh`:运行单GPU 345M参数GPT预训练(单GPU训练主要用于调试目的，因为代码针对分布式训练进行了优化).

修改DATA_PATH和CHECKPOINT_PATH路径后运行.
参数说明: `--micro-batch-size`为单个前向-后向路径的批处理大小，`--global-batch-size`为每次迭代的批处理大小，`--lr`为学习率，数据按949:50:1的比例划分为训练/验证/测试集(默认为 969:30:1),`--train-iters`为训练的迭代次数，或者使用`--train-samples`(训练的样本总数)，若使用`--train-samples`，则不需要指定`--lr-decay-iters`，而是需要指定`--lr-decay-samples`. `--lr-decay-iters`为学习率衰减迭代次数,`--fp16`为训练的数据类型,不设置默认使用fp32训练.

2. [pretrain_gpt_single_node.sh](example/pretrain_gpt_single_node.sh)

```
N_GPUS=1

CHECKPOINT_PATH=checkpoints/gpt2
VOCAB_FILE=gpt2-vocab.json
MERGE_FILE=gpt2-merges.txt
DATA_PATH=my-gpt2_text_document

RANK=0
WORLD_SIZE=$N_GPUS

GPT_ARGS=" \
    --num-layers 24 \
    --hidden-size 1024 \
    --num-attention-heads 16 \
    --seq-length 1024 \
    --max-position-embeddings 1024 \
    --micro-batch-size 4 \
    --global-batch-size 8 \
    --lr 0.00015 \
    --train-iters 500000 \
    --lr-decay-iters 320000 \
    --lr-decay-style cosine \
    --vocab-file $VOCAB_FILE \
    --merge-file $MERGE_FILE \
    --lr-warmup-fraction .01 \
    --fp16 \
    --rank ${RANK} \
    --world_size ${WORLD_SIZE} \
    --local_rank $RANK
    "

OUTPUT_ARGS=" \
    --log-interval 10 \
    --save-interval 500 \
    --eval-interval 100 \
    --eval-iters 10 \
    --checkpoint-activations \
    "

DATA_ARGS=" \
    --save $CHECKPOINT_PATH \
    --load $CHECKPOINT_PATH \
    --data-path $DATA_PATH \
    "

CMD="pretrain_gpt.py $GPT_ARGS $OUTPUT_ARGS $DATA_ARGS"

N_GPUS=1

LAUNCHER="deepspeed --num_gpus $N_GPUS"

$LAUNCHER $CMD
```
对于多GPU训练，修改`--num_gpus`所使用的GPU数量.

3. 模拟`distributed`
```
MASTER_ADDR=localhost MASTER_PORT=9994 RANK=0 LOCAL_RANK=0 python pretrain_gpt.py ...
```

更多命令行参数见 [`arguments.py`](./megatron/arguments.py).

### Deepspeed-PP和ZeRO-DP
使用Deepspeed的PP代替Megatron的PP,DP使用ZERO-DP，与Megatron-LM启动类似，此外还需要有一个deepspeed的配置文件和一些参数：
```
CHECKPOINT_PATH=checkpoints/gpt2
VOCAB_FILE=gpt2-vocab.json
MERGE_FILE=gpt2-merges.txt
DATA_PATH=my-gpt2_text_document
TENSORBOARD_PATH=output_dir/tensorboard
CODECARBON_PATH=output_dir/codecarbon

MICRO_BATCH_SIZE=1
GLOBAL_BATCH_SIZE=16
TP_SIZE=1
PP_SIZE=1

N_GPUS=2
SAVE_INTERVAL=100

RANK=0
WORLD_SIZE=$N_GPUS

GPT_ARGS=" \
    --num-layers 2 \
    --hidden-size 64 \
    --num-attention-heads 2 \
    --seq-length 1024 \
    --max-position-embeddings 1024 \
    --micro-batch-size $MICRO_BATCH_SIZE \
    --rampup-batch-size 2 2 1_000 \
    --global-batch-size $GLOBAL_BATCH_SIZE \
    --train-samples 100 \
    --optimizer adam \
    --adam-beta1 0.9 \
    --adam-beta2 0.95 \
    --adam-eps 1e-8 \
    --lr 1e-4 \
    --lr-warmup-samples 5 \
    --clip-grad 1.0 \
    --weight-decay 1e-1 \
    --vocab-file $VOCAB_FILE \
    --merge-file $MERGE_FILE \
    --fp16 \
    --rank ${RANK} \
    --world_size ${WORLD_SIZE} \
    --local_rank $RANK
    "

OUTPUT_ARGS=" \
    --log-interval 10 \
    --save-interval $SAVE_INTERVAL \
    --eval-interval 100 \
    --eval-iters 10 \
    --checkpoint-activations \
    "

DATA_ARGS=" \
    --save $CHECKPOINT_PATH \
    --load $CHECKPOINT_PATH \
    --data-path $DATA_PATH \
    --tensorboard-dir $TENSORBOARD_PATH \
    --tensorboard-queue-size 5 \
    --log-timers-to-tensorboard \
    --log-batch-size-to-tensorboard \
    --log-validation-ppl-to-tensorboard \
    "


ZERO_STAGE=1

config_json="./ds_config.json"

# Deepspeed figures out GAS dynamically from dynamic GBS via set_train_batch_size()
cat <<EOT > $config_json
{
  "train_micro_batch_size_per_gpu": $MICRO_BATCH_SIZE,
  "train_batch_size": $GLOBAL_BATCH_SIZE,
  "gradient_clipping": 1.0,
  "zero_optimization": {
    "stage": $ZERO_STAGE
  },
  "fp16": {
    "enabled": true,
    "loss_scale": 0,
    "loss_scale_window": 500,
    "hysteresis": 2,
    "min_loss_scale": 1,
    "initial_scale_power": 12
  },
  "steps_per_print": 2000,
  "wall_clock_breakdown": false
}
EOT


DEEPSPEED_ARGS=" \
    --deepspeed \
    --deepspeed_config ${config_json} \
    --zero-stage ${ZERO_STAGE} \
    --deepspeed-activation-checkpointing \
    "

ALL_ARGS="$GPT_ARGS $OUTPUT_ARGS $DATA_ARGS $DEEPSPEED_ARGS"

# if you can't stand pt-1.9 launcher noise
export LOGLEVEL=WARNING

LAUNCHER="deepspeed --num_gpus $N_GPUS"
export CMD=" \
    $LAUNCHER pretrain_gpt.py \
    --tensor-model-parallel-size $TP_SIZE \
    --pipeline-model-parallel-size $PP_SIZE \
    --distributed-backend nccl \
    $ALL_ARGS \
    "

echo $CMD

$CMD

```

### 分布式多卡训练
`examples/pretrain_gpt_distributed.sh`:使用Pytorch分布式启动分布式训练.
修改DATA_PATH和CHECKPOINT_PATH路径后运行.

使用两种类型的并行性：数据并行和模型并行.`--DDP-impl`是分布式数据并行的实现，设置为local是在反向传播是在反向传播时执行梯度全规约,设置为torch是将梯度规约与反向传播计算重叠.torch的分布式数据并行在较大的模型尺寸下更加高效.

开发了一种简单高效的二维模型并行方法。要使用张量模型并行(将单个transformer模块的执行拆分到多个GPU上)，添加`--tensor-model-parallel-size`指定要拆分模型的GPU数量，以及上述传递给分布式启动器的参数.要使用管道并行(将transformer模块分成阶段，每个阶段上具有相同数量的transformer模块，然后通过batch分解为更小的microbatches),添加`--pipeline-model-parallel-size`指定将模型拆分多个阶段的数量(若将有24个transformer层的模型拆分为4个阶段，则每个阶段有6个transformer层，即--pipeline-model-parallel-size 4).
使用模型并行训练参考：`examples/pretrain_gpt_distributed_with_mp.sh`.当前T5模型不支持管道并行.

### GPT-15B预训练

# 推理

## 模型转换

## GPT文本生成
`bash examples/generate_text.sh`

`--tensor-model-parallel-size`为tp数量，`--out-seq-length`为输出样本的长度，`--load`为加载的预训练检查点路径，`--num-samples`表示生成多少个样本，`--sample-input-file <filename>`可以将filename用作条条件文本，`--genfile`为无条件生成文本的保存文件.

```
CHECKPOINT_PATH=checkpoints/gpt2
VOCAB_FILE=gpt2-vocab.json
MERGE_FILE=gpt2-merges.txt
GPT_ARGS=" \
    --tensor-model-parallel-size 1 \
    --pipeline-model-parallel-size 1 \
    --num-layers 24 \
    --hidden-size 1024 \
    --num-attention-heads 16 \
    --seq-length 1024 \
    --max-position-embeddings 1024 \
    --micro-batch-size 4 \
    --global-batch-size 8 \
    --fp16 \
    "

MAX_OUTPUT_SEQUENCE_LENGTH=1024
TEMPERATURE=1.0
TOP_P=0.9
NUMBER_OF_SAMPLES=2
OUTPUT_FILE=samples.json

RANK=0
WORLD_SIZE=1

python tools/generate_samples_gpt.py \
    $GPT_ARGS \
    --load $CHECKPOINT_PATH \
    --out-seq-length $MAX_OUTPUT_SEQUENCE_LENGTH \
    --temperature $TEMPERATURE \
    --vocab-file $VOCAB_FILE \
    --merge-file $MERGE_FILE \
    --genfile $OUTPUT_FILE \
    --num-samples $NUMBER_OF_SAMPLES \
    --top_p $TOP_P \
    --recompute \
    --rank ${RANK} \
    --world_size ${WORLD_SIZE} \

```

# 参考
- [README_ORIGIN](README_ORIGIN.md)

