File size: 10,094 Bytes
8f8a944
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
==============
主要差异
==============

总览
=============

XTuner 可以复现 InternEvo (train_internlm) 仓库训练得到的开源模型
internlm/internlm2-chat-7b 的训练精度。

下面是 XTuner 和 InternEvo (train_internlm)
在相同数据集上训练相同基座模型的训练结果对比:

.. list-table::
  :widths: 50 25 25
  :header-rows: 1

  * - 能力类别
    - xtuner
    - internevo
  * - 全数据集平均(无智能体)
    - 56.44
    - 55.26
  * - 全维度平均(无智能体)
    - 49.58
    - 48.96
  * - 语言 Language
    - 64.77
    - 62.41
  * - 知识 Knowledge
    - 52.24
    - 52.52
  * - 推理 Reasoning
    - 65.5
    - 63.91
  * - 数学 Mathematics
    - 30.95
    - 30.26
  * - 代码 Coding
    - 38.91
    - 41.06
  * - 长文本 LongEval
    - 45.09
    - 43.62
  * - 智能体 Agent
    - 44.85
    - 43.97
  * - 数学题智能体
    - 37
    - 37.19
  * - CIBench
    - 79.07
    - 69.78
  * - PluginEval
    - 65.57
    - 65.62

64 \* A100 的训练时间对比如下:

=========== ==========
xtuner      internevo
=========== ==========
15 h 55 min 16h 09 min
=========== ==========

.. tip::
  使用 XTuner 提供的序列并行算法可以进一步提升训练速度,使用方式请参考
  \ :ref:`序列并行文档 <train_extreme_long_sequence>` \ 。


适配
==========

在从 InternEvo (train_internlm) 向 XTuner
迁移的过程中,我们需要关注模型、数据以及训练策略这三个方面的适配问题。后续内容将详细阐述如何进行适配。


模型
-------

InternEvo 在训练时读取和保存的模型权重满足以下目录结构(以 tp2pp2
为例):

.. code::

   |-- root
       |-- model_config.pt
       |-- model_tp0_pp0.pt
       |-- model_tp0_pp1.pt
       |-- model_tp1_pp0.pt
       |-- model_tp1_pp1.pt

其中,\ ``model_config.pt`` 保存模型权重的一些 meta 信息,其余 4 个
checkpoint 则分别保存 4 组 GPUs 上的模型权重。因此,InternEvo
训练过程中要求读取预训练权重的 tp、pp 策略与训练使用的 tp、pp
策略一致才能正常读取预训练权重进行训练。

XTuner 支持基于 Huggingface Hub 上的模型进行训练,如下修改 config
内容即可将基座模型从 internlm2-7b 切换为 internlm2-20b:

.. code:: diff

   #######################################################################
   #                          PART 1  Settings                           #
   #######################################################################
   # Model
   - pretrained_model_name_or_path = 'internlm/internlm2-7b'
   + pretrained_model_name_or_path = 'internlm/internlm2-20b'

数据
---------

InternEvo
在训练过程中通常会把多条数据拼接为一个特定的最大长度,随后输入模型训练。其配置往往满足以下形式:

.. code:: python

   data = dict(
       seq_len=SEQ_LEN,
       pack_sample_into_one=False,
       min_length=MIN_LENGTH,
       train_folder=TRAIN_FOLDER,
       dataset_weights=DATASET_WEIGHTS,
       ...)

其中,数据配比 (``dataset_weights=DATASET_WEIGHTS``) 功能 XTuner
尚未支持。\ ``TRAIN_FOLDER`` 中的训练数据需要满足 ftdp tokenized
数据集格式:

.. code::

   |-- TRAIN_FOLDER
       |-- cn
       |   |-- dataset1
       |   |   |-- data1.bin
       |   |   |-- data1.bin.meta
       |   |-- dataset2
       |   |   |-- data2.bin
       |   |   |-- data2.bin.meta

在 XTuner 中实现在线数据集拼接策略需要参考
``xtuner/configs/internlm/internlm2_7b/internlm2_7b_w_internevo_dataset.py``
文件中的配置:

.. code:: diff

   #######################################################################
   #                          PART 1  Settings                           #
   #######################################################################
   # Data
   - dataset_folder = '/path/to/sft/data/folder'
   + dataset_folder = TRAIN_FOLDER
   - max_length = 32768
   + max_length = SEQ_LEN

   #######################################################################
   #                      PART 3  Dataset & Dataloader                   #
   #######################################################################
   train_dataset = dict(
       type=build_packed_dataset,
       dataset_cfg=dict(
           type=load_intern_repo_tokenized_dataset,
           data_order_path=None,
           folder=dataset_folder,
   -       min_length=0,
   +       min_length=MIN_LENGTH,
           file_type='.bin'),
       packed_length=max_length,
       seed=1024)

.. note::

    需要注意,由于训练数据喂给模型的先后顺序可能对训练结果造成影响,因此建议不要轻易修改上述配置中的 ``seed`` 选项。同时,可参考 \ :ref:`获取数据顺序 <case4-step3>` \ 进一步固定数据顺序。

训练策略
------------

Varlen Attention
~~~~~~~~~~~~~~~~~~~~~~~~~~

InternEvo 通过设置
`数据配置 <https://github.com/InternLM/InternEvo/blob/77c3b46bfe51f6bc245c4aba98639221b8618372/doc/usage.md#%E6%95%B0%E6%8D%AE%E9%85%8D%E7%BD%AE>`__
中的 ``pack_sample_into_one`` 参数为 False
来使用“变长注意力机制”(见下图右侧)。

.. code:: python

   data = dict(
       pack_sample_into_one=False,
       ...)

.. raw:: html

   <html xmlns="http://www.w3.org/1999/xhtml"><head></head><body><div align="center">
     <img width="800" src="https://github.com/InternLM/InternEvo/blob/develop/doc/imgs/pack_into_one.png?raw=true" data-src="https://github.com/InternLM/InternEvo/blob/develop/doc/imgs/pack_into_one.png?raw=true" onerror="this.style.display = 'none';" />
     <br /><br />
   </div></body></html>

在 XTuner 中使用这一功能需要设置 config 中的 ``use_varlen_attn`` 配置为
True,即可保证训练行为与 InternEvo 一致:

.. code:: diff

   ...
   #######################################################################
   #                          PART 1  Settings                           #
   #######################################################################
   # Model
   pretrained_model_name_or_path = 'internlm/internlm2-7b'
   - use_varlen_attn = False
   + use_varlen_attn = True
   ...

.. warning::
   需要注意,当设置 ``use_varlen_attn = True`` 后,请确保
   ``batch_size`` 被设置为 1,且 ``pack_to_max_length`` 被设置为
   True。

.. tip::
  ``use_varlen_attn = True`` 时 ``单卡 batch size 等于 2,拼接数据集至最大长度 2k``
  的配置与 ``单卡 batch size 等于 1,拼接数据集至最大长度 4k`` 的配置训练行为是近似的,
  因此 XTuner 目前只支持了 ``batch_size_per_device = 1`` 的情况。


梯度累积
~~~~~~~~~~~~~~

在 InternEvo 的配置中,与 batch_size 和 accumulative_counts
相关的配置有如下几个:

.. code:: python

   data = dict(
       # micro_num means the number of micro_batch contained in one gradient update
       micro_num=MICRO_NUM,
       # MICRO_BATCH_SIZE * SEQ_LEN = PACKED_LENGTH
       micro_bsz=MICRO_BATCH_SIZE,
       total_steps=TOTAL_STEP,
       # 梯度累计,默认等于MICRO_NUM(BS)
       gradient_accumulation=GRADIENT_ACCUMULATION,
       ...)

.. note::
  InternEVO 中的 ``micro_num`` 等价于 XTuner 中的 ``gradient_accumulation``

.. note::
  ``total_steps`` 在 XTuner 中可以不手动指定,可通过 ``max_epochs`` 指定。

.. warning::
  XTuner 目前只支持 ``micro_bsz = 1`` 。

.. tip::
  为对齐以上配置,可参考 XTuner 中
  ``xtuner/configs/internlm/internlm2_7b/internlm2_7b_w_internevo_dataset.py``
  文件中的配置,并进行如下修改:

  .. code:: diff

    #######################################################################
    #                          PART 1  Settings                           #
    #######################################################################
    # Scheduler & Optimizer
    - accumulative_counts = 1
    + accumulative_counts = MICRO_NUM # or GRADIENT_ACCUMULATION
    - max_epochs = 1
    + max_epochs = MAX_EPOCHS

并行策略
---------------

ZeRO 系列显存优化
~~~~~~~~~~~~~~~~~~~~~~~

XTuner 支持使用 ZeRO 系列显存优化降低训练过程中的显存消耗:

.. code:: bash

     # 单卡
     xtuner train ${CONFIG_NAME_OR_PATH} --deepspeed deepspeed_zero2
     # 多卡
     (DIST) NPROC_PER_NODE=${GPU_NUM} xtuner train ${CONFIG_NAME_OR_PATH} --deepspeed deepspeed_zero2
     (SLURM) srun ${SRUN_ARGS} xtuner train ${CONFIG_NAME_OR_PATH} --launcher slurm --deepspeed deepspeed_zero2


序列并行
~~~~~~~~~~~~~~~~~~~

InternEvo 中支持了 Data Parallel、Tensor Parallel、Pipeline Parallel 和
Sequence Parallel 四种并行策略。XTuner 目前支持了 Data Parallel 和
Sequence Parallel 两种并行策略,可满足基本全部的训练需求(搭配 zero3
显存优化策略可支持 70B 模型 256K 上下文训练)。

假定 InternEvo 训练过程中:tp_world_size = TP, pp_world_size = PP,
sequence_parallel = True。则训练的 global_batch_size 满足以下计算公式:

.. code::

   # 多除的一个 TP 是因为启用了 sequence parallel
   global_batch_size = num_gpus * batch_size_per_device * gradient_accumulate / TP / PP / TP

.. tip::
  ``use_varlen_attn = True`` 时, ``batch_size_per_device`` 只能为 1,此时若想对齐
  ``global_batch_size``,只需要在配置文件中综合调整
  ``gradient_accumulate`` 和 ``sequence_parallel_size`` 两项的数值:

.. code:: diff

   + from xtuner.parallel.sequence import SequenceParallelSampler

   + sequence_parallel_size = SP
   - accumulative_counts = 1  # 1bs * 1acc * 64gpu = 64 batchsize
   + accumulative_counts = TP * PP * TP / SP

   #######################################################################
   #                      PART 3  Dataset & Dataloader                   #
   #######################################################################
   train_dataloader = dict(
   -   sampler=dict(type=DefaultSampler, shuffle=True),
   +   sampler=dict(type=SequenceParallelSampler, shuffle=True),
       ...)