LLMのトレーニング(事前学習や継続学習)は膨大なGPUリソースかかりますので、試したこともなく、いつもどうやって行っているのか疑問になっていました。
最近、中国のBaichuan(中国で有名なLLM)の技術レポートを読んだところ、LLMのトレーニング流れについて書かれていましたので、そのプロセスをある程度理解することができました。(このレポートは、おそらく唯一のLLMトレーニングの過程を全て公開したレポートだと思います。一般的には、LLMのトレーニングに関するレポートは精度の紹介にとどまり、詳細なプロセスやコツはほとんど公開されないため、これ読むことで結構勉強になりました。)
まずすべてのLLMは分散学習でトレーニングします。
なぜ分散学習が必要かというと、LLMをトレーニング際に学習するパラメーターの数が少なくとも数十億にも及ぶため、一台のGPUのメモリでは学習できないです。
分散学習には主に2種類の分散方法があります。それは、データ並列(DP: Data Parallelism)とモデル並列(MP: Model Parallelism)です。
データ並列(DP: Data Parallelism)
データ並列は、すべてのGPU上で同じモデルを実行し、それぞれのGPUで異なるデータセットを使ってモデルをトレーニングする手法です。トレーニング後、各モデルのパラメーターの平均値を計算してパラメーター値を修正します。
計算を担当したGPUはWorkerと呼ばれ、勾配集約を担当したGPUはServerです。Serverは他のWorkerへ勾配を通信しますから。この計算を行うGPUは「Worker」と呼ばれ、勾配を集約するGPUは「Server」と呼ばれます。Serverは他のWorkerに勾配情報を伝達する役割を持ちますが、通信のボトルネックはServerに存在します。通信コストの大きさと負荷がコントロールしにくいために、データ並列は通常、単一のマシンに複数のカードがある場面で使用されます。また、データ並列は一台のGPUでは実行できないサイズのモデルには適用できないため、データ並列のみ使うと最近の大規模LLMのトレーニングはできないです。
モデル並列(MP: Model Parallelism)
モデル並列は、パイプライン並列(PP:Pipeline Parallelism)とテンソル並列(TP:Tensor Parallelism)に分けられます。パイプライン並列は、モデルをいくつかの段階に分割し、それぞれの段階を複数のGPUに分散させます。一方で、テンソル並列では、モデルの異なる計算部分を複数のGPUに分散させる手法ます。("段階"と"計算部分"の違いについては私もよくわからなかったです)
これら2種類の分散方法を組み合わせることにより、さまざまなLLMのトレーニングアーキテクチャが構築されています。
一般的なLLMトレーニングアーキテクチャには、Megatron、DeepSpeed(Zero)、Accelerateなどがあります。
最も人気あるのは、Microsoftによって開発されたDeepSpeedです。DeepSpeedはパラメーターを分散させることで、トレーニング時間とメモリ消費を大幅に削減することができます。(ファインチューニングの場合にも使われます)
AccelerateはHuggingFaceが提出した軽量アーキテクチャで、小規模なモデルのトレーニングに向いてます。
これらのアーキテクチャは一緒に使うこともできます、例えばMegatron-DeepSpeedというのはMegatronとDeepSpeedを結合したものです。(baichuanもこのアーキテクチャでトレーニングされてます)
今後もし機会あれば、分散学習でプレトレーニングも試してみたいと思います。
DeepSpeedについて:
DP:
baichuanのレポート: