メモリをスワッピングしながら大規模言語モデル(LLama2)をフルパラメータでファインチューニングできるかどうか?

背景

大規模言語モデルの学習には、大量のメモリ容量が必要になります。
例えば700億パラメータ(70b)のモデルを16bit変数で読み込むだけでも70 GB程度の容量が必要で、学習にはその10倍程度の容量くらいはあると安心です。

ただし、学習に必要なGPUは高額(A100の80GBモデルは200万円超)なので、多額の資金が必要になります。

打開策として、有名なQLoRAのほか、学習に必要なメモリをCPUやSSD(NVME)に移す(オフロード)するテクニックなどがあります。

しかし数テラバイトのCPUメモリやSSDを増設するにも、それなりの手間とコストがかかります。

そこで今回は、外付けSSDにメモリスワップさせる形で、大規模言語モデルのメモリをオフロードできないか、無謀な挑戦をしてみます。

デバイス

今回用いたSSDはこちら。メモリは4TB、転送速度は最大2GB/sです。

更に早い規格(Thunderbolt™4: 40Gbps)も存在するようですが、用いるマシンの端子が対応しているか不明だったので、こちらの品にしました。

GPUなどに比べ、圧倒的にSSDの転送速度が遅い点に注意が必要です。GPU(や最先端のCPUメモリ)だとテラバイトレベルの帯域があります。
なので、今回の構成では、読み込み・書き込み速度が1/1000程度に落ちる可能性があります。

実装

スワップメモリの確保

nvme対応のSSDであれば、単純にdeepspeedのjson設定を"nvme"に変更するだけでOKです(リンク)。
今回のデバイスはnvme対応ではなかったので、cpuメモリにオフロードしつつ、不足部分をlinuxのスワッピング機能で補う戦略を取ります。

SSDをフォーマットします。(今回のケースでは、SSDは/dev/sdb2で認識されました)

 sudo mkfs.ext4 /dev/sdb2

スワップ領域を作り、有効化します。

sudo mkswap -c /dev/sdb2
sudo swapon /dev/sdb2

4TBもあるので、処理にはそれなりの時間がかかります。
一晩放置したら、無事にスワッピングメモリが追加されていました。

topコマンドでのメモリ確認の様子。251 GBのCPUメモリが少なく見えるほどのSwap容量です。

実装

学習のコード自体は、以下の記事を流用しました。

最大 150 token程度のテキストを学習させてみます。
モデルにはLLama2を使いました。
マシンはRTX3090(24 GB) x1 + CPU RAM 256 GBの構成です。

メモリの使用状況

・7b (合計メモリ: 約 220 GB) 速度: 13 sec/iter
6 GB(GPU) + 210 GB (CPU) + 0.7 GB (SSD)
→ 7bはメモリスワップなしで動きました。

ちなみに、1500 tokenだと20GB程度のVRAMを要しました。

・13b(合計メモリ: 約310 GB) 25 sec/iter
6 GB(GPU) + 220 GB (CPU) + 80 GB (SSD)
→ 256 GBのCPUメモリでは足りず、追加で80GB程度のスワップメモリが必要になりました。
学習速度は7bと比べると半分程度に落ちました。
ただ、モデルサイズが大きくなると学習速度は落ちるので、意外と頑張っているしている印象です。

70b (out of memory)
→cuda out of memoryでした。VRAMの増強が必要そうです

注意

13bモデルの学習中に、コンピュータがフリーズしてしまいました。なので、学習は数stepしか試せていません。
使っているマシンのハードウェアが若干、不安定なことも関連かもしれませ。

まとめ

  • メモリスワッピングを使えば、大型のモデルのフルパラメータ ファインチューニングができる可能性を示しました。

  • ただし、70bレベルだったりtoken長が大きいと、どうしてもGPUメモリが必要になるようです。

    • A100 x2 + 数TBの追加メモリで70bクラスも動くかどうか、気になるところです

  • スワッピングしすぎるとシステムが不安定になる感じなので、素直にNVMEでオフロードした方が良さそうです。







いいなと思ったら応援しよう!