ニュース

ベアメタルから 700 億のパラメータを備えた大規模モデルまで、チュートリアルとすぐに使えるスクリプトがここにあります

2024-07-24

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina



imbue.com から選択

著者: インビューチーム

マシンハートコンピレーション

編集者:パンダ

LLM が大量のデータを使用して大規模なコンピューター クラスターでトレーニングされていることはわかっています。Machine Heart は、LLM トレーニング プロセスを支援および改善するための多くの方法とテクノロジーを導入しました。今日私たちが共有したいのは、基礎となるテクノロジーを深く掘り下げ、オペレーティング システムすら持たない多数の「ベア メタル」を LLM のトレーニング用のコンピューター クラスターに変える方法を紹介する記事です。

この記事は、機械がどのように考えるかを理解することで一般的な知能の実現に努めている AI スタートアップ企業 Imue によるものです。

もちろん、オペレーティング システムを持たない大量の「ベア メタル」を LLM をトレーニングするためのコンピューター クラスターに変換することは、探索と試行錯誤に満ちた簡単なプロセスではありませんが、Imbue は最終的に 700 億のパラメーターを備えた LLM のトレーニングに成功しました。その過程で役立つ多くの経験。

この記事では、チームが独自の LLM トレーニング インフラストラクチャを構築するプロセス全体を詳しく紹介し、監視、検査、エラー修正を容易にするためにチームが作成した多くのツールとスクリプトを共有します。

独自の LLM トレーニング インフラストラクチャの構築に興味がある場合、または LLM がどのように作成されるかに興味がある場合は、この記事を読んで収集する価値があります。

以下は Imbue チームの記事の原文です。

導入

研究者とエンジニアの小規模チームは、数か月をかけて独自のインフラストラクチャ上で 700 億パラメータのモデルをゼロからトレーニングし、そのモデルは推論関連のタスクでゼロショット モデルを上回りました。

本日は、初期クラスターの構築からオペレーティング システムのインストール、トレーニング中にエラーが発生した場合の自動回復の設定まで、必要なインフラストラクチャをセットアップするプロセスを共有します。各ステップで直面する課題と解決策について詳しく説明します。これらの学習に加えて、他のチームが独自のモデル トレーニング用に安定したインフラストラクチャを簡単に作成できるようにするために、これまでに開発したスクリプトの多くもリリースする予定です。

プロセス全体を通じて、当社のエンジニア チームは Voltage Park と協力してコンピューター クラスターを準備し、実稼働アプリケーションの基盤を構築しました。このプロセス全体には次のものが含まれます。

1. 各マシンの設定

2. インフィニバンドの設定

3. マシンが完全に正常であることを確認します

4. 一般的なトレーニングの問題を診断する

5. インフラストラクチャツールの改善

各ステップについては、以下で詳しく説明します。

背景: どのように作られたか

計算を実行する際の目標は、大規模な言語モデルを確実に迅速に実験できるようにすることです。これを行うには、多数の高速 GPU と、これらの GPU 間の高速通信が必要です。

この記事では、511 台のコンピューターに分散された 4088 個の H100 GPU、つまりコンピューターごとに 8 個の GPU を含むクラスターに焦点を当てます。 GPU を搭載したコンピュータが 511 台ある理由は、InfiniBand ネットワークを管理する役割を持つ Unified Fabric Manager ノード用に一部の接続を予約する必要があるためです。 511 GPU 搭載ホストでは、各 GPU が ConnectX-7 ネットワーク カードに直接接続されており、InfiniBand ネットワーク上の任意の GPU に 400 Gbps でデータを送信できます。

当社の InfiniBand ネットワーク トポロジは理論的には「完全にノンブロッキング」であり、これにより GPU が最大速度で相互に通信できるようになります。これを実現するために、3 層 InfiniBand ネットワーク アーキテクチャ、つまり 3 層 InfiniBand スイッチを使用します。適切な接続を使用すると、ネットワーク全体でこの高レベルのスループットを実現できます。次の図は、この InfiniBand ネットワークの概要を示しています。



ネットワークのトレーニング中の通信は、イーサネットではなく、InfiniBand 経由で行われることに注意してください。これらのマシンもイーサネットに接続されていますが、このネットワークの役割はデータセットやチェックポイントなどのデータを転送することです。イーサネットを使用してデータを送信する場合、データは最初に GPU から CPU に送信され、次に 100 Gbps 速度のイーサネット カードを経由して送信されるため、速度は大幅に遅くなります。 RDMA over Converged Ethernet (RoCE) と呼ばれるテクノロジーを使用してイーサネット上でトレーニングすることも可能ですが、ハードウェア側とソフトウェア側の両方で多くの追加作業が必要となり、一般に InfiniBand よりも信頼性が低くなります。詳細については、この論文を参照してください: https://arxiv.org/pdf/2402.15627

構成と管理のみに使用されるセカンダリ イーサネットもあり、BIOS (基本入出力システム)、電源、および低レベルのマシン インターフェイスのその他の制御インターフェイスへのアクセスを提供します。この管理ネットワークがなければ、USB ドライバー、キーボード、モニターを使用して各ノードを手動でセットアップする必要があります。何百ものマシンがある状況では、これは持続可能なアプローチではありません。

このクラスターで高パフォーマンスのトレーニングを実現するには、すべてのコンポーネント (InfiniBand、イーサネット、GPU、ノード自体) がほぼ完璧に動作する必要があります。これら 12,000 以上の接続のいずれかが少し不安定であると、トレーニング全体の実行が遅くなる可能性があります。

この記事の残りの部分では、すべてを完璧かつ安定して実行する方法について説明します。

プロセス: ベアメタルを完全に動作するクラスターに変える方法

各マシンを設定する

管理ネットワーク経由でクラスターへの最初のイーサネット接続を確立した後、ベースボード管理コントローラー (BMC) へのアクセス資格情報が取得されます。 BMC は、ホスト システムをリモートで監視する専用のサービス プロセッサであり、通常は別のネットワークに接続されます。これにより、あたかもその場にいるかのようにマシンを操作できるようになり、さらにハードウェアの健全性、BIOS 設定、電源管理のための API も提供されます。

これらのコンポーネントを配置したら、すぐにクラスターのセットアップを開始できます。

ステップ 0: 最初にマシンを構成する

まず、iDRAC (Dell のベースボード管理コントローラー) を使用してサーバーに Ubuntu 22.04 をインストールし、その後、このオペレーティング システムに基づいて他のすべてをセットアップしました。 iDRAC の機能の 1 つは、ローカル コンピュータからの ISO イメージのインストールと起動を可能にし、ブラウザを介して仮想コンソールを提供することです。理想的には、これがプロセスにおける唯一の手動インストール手順です。

ステップ 1: 各マシンにオペレーティング システムをインストールする

最初のマシンを構成した後、残りのサーバーの構成に役立つ Ubuntu の Metal-as-a-Service (MAAS) ソフトウェアのインストールに進みます。 iDRAC ブートおよび自動化ツールは、Preboot Execution Environment Protocol(PXE)を使用して、各マシンにネットワークから起動するように指示し、PXE ブート要求に応答するように MAAS を設定します。初期ネットワーク ブートを実行するとき、サーバーはローカル ドライブに何もインストールすることなく、動的 IP 割り当てプロトコル DHCP 経由で MAAS から IP と初期カーネルを取得します。これは、繰り返し可能なオペレーティング システムのインストールを自動化するための基本環境です。理論的には、最初の起動を待つだけですべてが処理されます。しかし実際には、MAAS と BMC の統合は信頼性が低いため、iDRAC API を使用して各マシンの MAC アドレス (一意の物理ハードウェア識別子) を事前に収集します。

このトレーニング プロセス全体を通じて、MAAS は椎骨スタックのより信頼性の高いコンポーネントであることがよくあります。ただし、最初に、私たちのセットアップに特有の問題がいくつか発生しました。たとえば、最初の数台のマシンを構成するとき、クロックが大きく異なるため、HTTPS 証明書の検証の問題により、apt 経由で何もインストールできませんでした。関連して、MAAS サーバーは多くのこと (DHCP サーバー、ホスト名を IP に解決する DNS サーバー、ホストと公式 Ubuntu パッケージ サーバー間の HTTP プロキシ、NTP サーバー、cloud-init 構成管理、グラウンド) を担当する必要があるため、 MAC アドレス、IP、ホスト名、カスタム メタデータを接続するために使用される真実データベース)のため、これらの問題を根本原因から解決することは困難です。さらに、設計目標は、グリーンフィールド展開の管理の複雑さと、ノードとさまざまなデバッグ/異常な中間状態の段階的な移行に対処することであるため、MAAS 構成ライフサイクルの学習曲線の問題もあります。

ステップ 2: 壊れたマシンを診断する

約 10% のマシンが起動に失敗しており、その主な原因はサーバーの物理的な問題であることがわかりました。これは、大規模な GPU クラスターをセットアップするための一般的なシナリオです。私たちが遭遇した状況には、ネットワーク ケーブルの欠落または間違ったもの、iDRAC のハードウェアの問題、電源ユニットの破損、NVME (不揮発性メモリ高速) ドライバーの破損、内部回線の欠落、ネットワーク カードまたは GPU の表示なしなどがあります。これらの問題を自動的にチェックし、再テストのために一部のマシンをデルに返却し、データセンター スタッフに適切な作業指示を提出しました。クラスターを自分で構成する利点の 1 つは、一部のマシンのメンテナンスを待っている間、正常なマシンをすぐに使用できることです。

ステップ 3: 実行可能な最小限の観察可能なマシン

各サーバーで次の設定を続けます。

1.Docker (サービスとトレーニング ジョブの実行を容易にするため)

2. データセンターGPUドライバー

3. Prometheus ノード エクスポート ツール (安定したハードウェア/オペレーティング システム インジケーターのデータ フローをエクスポートするために使用)

4.DCGM エクスポート ツール (GPU ステータス、クロック、使用率など、NVIDIA GPU から追加のインジケーター データをエクスポートするために使用されます)

5. すべての非オペレーティング システム ドライバー用の RAIDZ ZFS プール。これにより、ドライバーに障害が発生した場合でもマシンが動作し続けることができると同時に、透過的な圧縮も無料で提供されます (これは、プレーン テキスト データ セットや反復的なログに特に役立ちます。これを使用すると比較的便利です)通常、ツールを使用すると、このツールを使用しない場合と比較して、使用可能なスペースが最大 10 倍増加します)

次に、基本的な GPU 診断を実行して、GPU が通常適切に機能しているかどうかを判断します。正常に機能していない場合は、通常、数時間以内にハードウェアの問題が発生します。

この間、400 ノードすべてにパッケージを同時にインストールしようとすると、帯域幅のボトルネックが発生しました。データセンターに導入された複数のコンポーネントで高温過熱アラートを受信したのはこれが初めてです。これらの最初の発熱問題は、ファームウェアのアップデートによって大部分が解決されました。

ステップ 4: 単一ノードの GPU トレーニング

次のステップは、各マシンが実際の G​​PU ワークロードを独自に処理できることを確認することです。多くのマシンはこれを行うことができず、次のような問題があります。

GPU 関連のエラー。通常、GPU カードをカード スロットに再挿入することで解決できます。200 ポンドのサーバーをラックからスライドさせて取り出し、カバーと GPU の間のすべてのケーブルを取り外し、GPU を取り外し、GPU を再取り付けします。ケーブルを再接続し、サーバーをラックに押し戻します。

Ubuntu サーバーのログによると、GPU と PCIe バスまたはネットワーク カード間の多くのケーブルで「幅が制限されています: x4 < x16」というエラーが発生しました。 PCIe スイッチ バス ファームウェアを更新した後、ホストの約 4 分の 1 が内部 PCIe ケーブルを接続し直す必要があることがわかりました。これはおそらく、ケースと GPU の間のケーブルが非常に壊れやすいためです。つまり、GPU でメンテナンスを実行するたびに、これらのケーブルが破損してしまうためです。押されたり、引き抜かれたり。

いくつかのさまざまな停止が発生し、複数のホストにも影響を及ぼしました。デルは、ファームウェアのアップグレードに関するいくつかの問題の解決を支援してくれました。

NVMe ドライブには問題はありませんでしたが、触れるとマシン全体がロックされました。

Linux ではハード ドライブがランダムな順序で表示されるため、MAAS で混乱が生じ、オペレーティング システムが間違ったドライブにインストールされてしまいます。

温度の測定値が間違っているため、ファンが常にフルスピードで動作します。原因は NVIDIA ドライバーに問題がある可能性がありますが、ドライバーのバージョンをダウングレードすることで解決できます。

CPU の動的スケーリングが制御不能になり、動作コアが 2 GHz に制限されました。

直接 GPU-GPU 通信 (GDR または GPUDirect RDMA Peer Memory Client) を正常に適用できません。

インフィニバンドの構成

ステップ 0: UFM をインストールする

InfiniBand の利点の 1 つは、ネットワーク全体が 1 つの頭脳を持つように集中化された設計であることです。したがって、ネットワーク構造全体で 320 ネットワーク スイッチの 1 つのインスタンスのみを処理する必要があります。私たちの最初のタスクは、どのスイッチがどのマシンに接続しているかを把握し、それを配線図と関連付け、スイッチの物理的な位置に基づいてスイッチの名前を変更することでした。

ステップ 1: 再配線

当初、UFM は、ファブリック内に存在するはずのホストはおろか、これらの 320 スイッチを検出できませんでした。データセンター パートナーと相談した結果、スイッチの電源がオンになって配線されていることを確認しましたが、依然としてスイッチを検出できませんでした。ネットワークのケーブル配線リストを調べた結果、ネットワーク構造のトップレベルの設計が間違っていることに気付きました。構造は統一される代わりに、共通のルーティング パスを持たない 8 つの切断されたネットワークに分割されていました。再配線後、すべての物理接続が新しい設計と一致していることを確認するチェック手順を追加しました。

ステップ 2: 1 万件の温度アラーム (アラート)

物理配線の問題が解決された後、InfiniBand はネットワーク ファブリック内のすべての InfiniBand スイッチへの接続を正常に確立しました。しかし、ほぼすべてのスイッチ ポートが、データを送信していないにもかかわらず、過度の温度 (場合によっては 70°C を超える) を報告し始めました。この問題は、同じラック内のスイッチ間の空きスペースが原因で、熱気が前面に逆流することが原因であることがわかりました。データセンター パートナーは、問題を迅速に診断し、適切な解決策を開発するのに役立ちました。

ステップ 3: 1800 件のアラーム

また、多くのポートではエラー率が高く、通常の状態と破損した状態の間を行ったり来たりする「フラッピング」と呼ばれます。これらの問題は、ポートが実際に使用される場合にのみ発生します。また、構造全体が 10,000 の高度に冗長なリンクで構成されているため、事前に検出することは困難です。当社のデータ センター パートナーが警報ポートの清掃と再取り付けを支援し、交換を待つ間残りの警報トランシーバーを無効にしました。

InfiniBand はハードウェア障害に対して回復力がありますが、ファブリックの約 10% で障害が発生し始めると、適応ルーティングなどの機能が時折失われるリンクを考慮して確実に動作しなくなります。

この間、100 ~ 200 台のマシンを使用してマルチノード トレーニングを実行することに成功しました。私たちのプロセスはある程度即興的なものです。時々、ランダムなノードのセットを起動し、そのパフォーマンスを観察し、できるだけ多くのノードを実行し続けるように努めます。この方法を使用すると、InfiniBand ネットワーク構造の信頼できるサブセットを見つけることができますが、毎回トレーニングに使用されるノードのセットを変更する必要があり、それによってデフォルトの InfiniBand リンクが変更されるため、これは非常に困難です。

ステップ 4: InfiniBand が狂ったように燃え上がる

InfiniBand の問題をより効率的に診断するために、ファブリック内のすべてのポートを通じてできるだけ多くのデータを同時にプッシュするクラスター全体のワークロードを設計しました。これは、クラスタ全体で大規模な all-reduce ワークロードを実行することとは異なります。この場合、NCCL を使用して、サーバー PCIe モジュール (SXM) スロットを介した GPU 通信に NVLink を使用して個々のノード間の通信を最適化する必要があります。

代わりに、強引なアプローチを選択し、簡単に成功しました。 UFM は、ほとんどのポートのデータ転送量が理論上の容量の 97% を超えるとアラートの発行を開始し、一部のスイッチが一時的にダウンします。その日の終わりまで生き残ったと思われるすべてのポートは十分に堅牢でしたが、残りのポートは無効になるか、修理が保留されて削除されました。

ステップ 5: GPUDirect RDMA

CPU コンピューティングのオーバーヘッドを発生させずに GPU 通信を可能にするために、InfiniBand ネットワーク カード間の直接通信を可能にする GPUDirect RDMA と呼ばれる機能を有効にしました。これには、次の 2 つの重要な手順が含まれます。

1. 追加のカーネルモジュールを起動します

2. 即時ハング (即時ハング) を防ぐために、PCIe アクセス コントロール サービス (ACS) が無効になっていることを確認します。

ステップ 6: 「ゴールド」サーバーを拡張する

最新のハードウェアを使用して GPU クラスターを構築するには、経験則として、毎週約 3% のマシンに障害が発生することを覚悟する必要があります。

ただし、すべてのマシンが均一に 3% の故障確率を持つわけではなく、少数の未処理のマシンでは、適切に修理されるまでさまざまな問題が繰り返し発生することに注意してください。これは、同じネットワーク構造内に多数のマシンがあることの利点を強調しています。したがって、モグラたたきで何が壊れているかを確認するように、大規模なトレーニングを実行するマシンをランダムに見つけるだけではなく、信頼できることがわかっているサーバー、つまり「ゴールデン」サーバーのスケーリングに重点を置くのが私たちのアプローチです。

ステップ 7: メンテナンス

InfiniBand のメンテナンスには主に、UFM アラームへの対応、障害のあるケーブルとトランシーバーの交換、および場合によってはより困難なエラー (スイッチ障害など) の診断が含まれます。通常、大規模なメンテナンスが発生する要因は 2 つあります。

1. ファームウェアのアップデート、特にクラスタの半分だけがアップデートを完了している場合、UFM 状態が破損し、すべての InfiniBand スイッチで UFM の再起動が必要になる可能性があります。

2. GPU ボックスが同時に大規模に再起動されるため、UFM 状態に多数の更新が挿入され、UFM サービスの再起動も必要になる場合があります。

マシンが完全に正常であることを確認してください

その過程で、個々のマシンが誤動作したりトレーニングが遅くなったりする可能性がある複数の原因を発見しました。これらの障害モードの多くはすぐには明らかではないため、ホストが十分に健全であるかどうかを確認するために、多数のヘルス チェック スクリプトを作成しました。ここでコードを公開しました: https://github.com/imbue-ai/cluster-health

これらのヘルスチェックの多くはランタイム環境に固有のものであり、必ずしも基盤となるハードウェアに関連しているわけではなく、修正や自動化が必ずしも簡単ではないことに注意してください。これは仕様によるものです。マシンをトレーニングできる状態にするという全体的な目標を達成するには、「はい」か「いいえ」で簡単に答えられ、細かい詳細をいくらでも要約できる単一のエントリ ポイントが必要でした。

GPUのヘルスチェック

GPU の数が正しいこと、ECC (エラー訂正コード) チェックが有効であること、および ECC エラーがないことを確認しました。また、NVLink トポロジ (GPU を相互に接続する) がエラーなく稼働していることも確認しました。

ディスク容量のヘルスチェック

ホストのディスク領域使用率が 95% を超えているかどうかを確認しました。

Docker ヘルスチェック

Docker が GPU に接続された状態でコンテナを実行できること (つまり、NVIDIA Container Runtime が適切に動作していること)、および監視/分析に関連する Docker コンテナがアクティブ化されていて、正しいホスト権限があることを確認しました。

Dmesg ヘルスチェック

dmesg でハードウェア Xid または SXid エラー (NVIDIA GPU または GPU 間 NVIDIA スイッチによって引き起こされる障害) をチェックしました。また、すべての dmesg ログ行を読み取り、それらがすべて共通/予期されるログ行リストに分類できることを確認します。

iDRAC ヘルスチェック

マシン上の iDRAC エラーをチェックしましたが、致命的ではないエラー メッセージは無視されました。これは Dell コンピュータに固有のチェックであるため、オープン ソース コードには含まれていません。

ディスクのヘルスチェック

zpool がインストールされていること、Docker がそれに適切に接続されていること、そして CPU をロックアップすることなく実際にそれに到達できることを確認しました。

InfiniBand ヘルスチェック

InfiniBand のエラー率が増加していないか、ドライバーのファームウェアが古いかどうかを確認しました。

Nvlink ヘルスチェック

マシン上の NVLink エラーを確認しました。実際には、これによってトレーニングの失敗が発生することはないようですが、トレーニングの速度が低下する可能性があります。

東ドイツの健康診断

マシン上で GDR が有効になっているかどうかを確認しました。

VBIOS ヘルスチェック

GPU の VBIOS バージョンと H100 ベースボード ファームウェアが最新であることを確認しました。

フリントの健康チェック

flint と hca_self_test を使用して、Mellanox OFED ドライバー、ネットワーク カード ファームウェア、およびトランシーバー ファームウェアが正しいバージョンであること、およびそれらが NVIDIA ドライバー用に正しくコンパイルされていることを確認しました。

PSB ヘルスチェック

PCIe デバイスにクエリを実行して、GPU、PSB (PCIe スイッチ バス)、ネットワーク カード間の接続速度と幅が期待どおりであるかどうかを確認しました。スイッチのファームウェアが最新であることも確認しました。このスクリプトは Imbue ではなく Dell によって開発されたため、現時点では共有できません。

これらの簡単なヘルス チェックに加えて、次のようなより複雑なヘルス チェックも実行します。

PyTorch を通じて行列計算を初期化し、NVLink 帯域幅、GPU 計算速度、メモリを測定します。 InfiniBand と NVLink をテストするために、適切な GDR フラグを設定します。

ib_write_bw および –use_cuda を使用して、IB カード経由でデータを送信し、PCIe および InfiniBand カードの帯域幅を測定します。このプロセスは、点滅する InfiniBand リンクが確実に見つかるまで、長時間 (約 15 分) 続きました。

マルチノード診断を実行して、NCCL の初期化機能と、それがランダムに停止するかどうかを確認します。一時停止がある場合、フォークされた NCCL コードにより追加のログが追加されます。問題を検出するには 12 ~ 24 時間かかるため、通常は新しいノードでのみ、または問題が疑われる場合にのみこれを実行します。

DCGM エクスポートで GPU クロック スロットリング イベントがないか確認します (予期される gpu_idle と power_cap を除く)。これらの電力イベントをチェックするには、すべての GPU、InfiniBand カード、CPU とディスクを同時にチェックするマルチノード トレーニングを実行するのが最善の方法です。

一般的なトレーニングの問題を診断する

ハードウェアが適切に動作すると、トレーニングを開始できます。

このセクションでは、クラスター上で大規模な言語モデルのトレーニングを実行した経験に基づいて、いくつかの具体的なデバッグ手順と洞察を共有します。

起動時にクラッシュする

ある意味、これは遭遇する可能性のある最高のバグです。なぜなら、これは (理論的には) 簡単に再現して反復できるからです。

まず、コードが正しいバージョン、構成、環境変数で実行されていることを確認しました。基本的ではありますが、スタートアップ トレーニング プロセスが再現可能であり、チェックしやすいものであることを保証することが重要であることがわかりました。理由の 1 つは、Docker イメージのキャッシュや不透明なシークレット構成などの中間抽象化が混乱を引き起こす可能性があることです。

私たちが実行するもう 1 つの基本的なチェックは、すべてのマシンがオンラインになっていること、および出力されたスタック トレースまたはログが簡単に集計および検査できることを確認することです。ここでは Loki、Prometheus、および Grafana ソフトウェア スタックを使用しましたが、適切なログ集約または追跡 SaaS ツールであればどれでも使用できます。これらのトレーニングの実行は本質的に同期的かつ分散されるため、多くの場合、最初のエラーが無関係なエラーの連鎖につながります。ここで、ヘルスチェックは、ハードドライブの破損、GPU の欠落または無効などのエラーを即座に検出するのにも役立ちます。

障害が発生した場合に自動的に再起動するシステムを構築しました。そのため、さまざまな再起動による混乱を招くエラーを避けるために、ログとエラーの集計がさらに重要になります。遭遇する一般的なエラーには次のようなものがあります。

1. 「前方順序がランク間で異なります。ランク 0 は 43 個のパラメータをすべて収集していますが、ランク 1228 は 1 個のパラメータをすべて収集しています」のようなエラー。これは PyTorch の Fully Sharded Data Parallel (FSDP) 実装の奇妙な機能であることがわかり、再起動すると解決されました。

2. 次のような GPU メモリ不足 (OOM) エラー: 「CUDA メモリが不足しています。割り当てようとしました...」 構成とコードを複数回チェックし、最近のコード変更を元に戻すことによって (実行中の PyTorch デバイスの仕様が間違っていたため)起動が遅くなり、GPU#0 が過剰に使用される問題を修正しました。

3. CPU/RAM メモリ不足 (OOM) エラー。これらのエラーはエラー ログで見つけるのが簡単ではありませんが、通常は Docker コンテナの外部にあるホストの dmesg ログを通じて検出できます。 OOM Killer がフォークされたプロセスまたはネットワーク ピアを停止するために呼び出した場合、それらは主に CalledProcessError または ConnectionError として現れることがわかります。 OOM Killer 呼び出しが dmesg から検出された場合、単純にヘルスチェックを放棄してボックスを再起動することを好みます。また、手動ガベージ コレクションが適切に行われているかどうかコード パスをチェックし (これを無効にする方法については以下のセクションを参照)、また、計算を実行したり、テンソルを CPU に移動しようとする予期せぬ試みがないかどうかもチェックしました。

トレーニング中のクラッシュ

最優先事項は、システムを自動化して、すべてのヘルス チェックを自動的に再実行し、異常なホストが見つからない場合は再起動できるようにすることです。 Xid エラーや SXid エラーなど、いくつかのランダムなハードウェア エラーが発生しました。これらのエラーにより、意味のある Python スタック トレースが出力されずに実行がクラッシュする可能性があります。行の再マッピングなどの一部の問題は、再起動することで回復できます。修正不可能な ECC エラーなどの他の問題では、多くの場合、ハードウェアのメンテナンスや部品の交換が必要になります。

さらに、不正な形式のトレーニング データもクラッシュを引き起こす可能性があることを確認しました。たとえば、コーパス内に非常に大きな単一のドキュメントがある場合、GPU または CPU でメモリ不足エラーが発生する可能性があります。この問題を防ぐために、完全に決定的なデータ ローダーを使用し、エポックまたはステップ番号に関連付けることですべてのクラッシュを簡単に再現できるようにします。データのロードを無効にするか、偽のデータ (すべてゼロのデータなど) を置き換えることで、エラーの根本原因がデータにあるかどうかを確認するのに役立つことがわかりました。

最後に、メトリック集計方法を使用してネットワークおよび一般的なノードの健全性統計を記録することも役立ちます。イーサネットの短時間の切断やディスク容量の不足などの問題は、有益なエラー メッセージとして表示されない場合がありますが、収集されたデータと簡単に関連付けることができます。

スタック トレースなしでハングする (後でタイムアウトの問題が発生する可能性があります)

これらの問題に関する有用な情報が不足しており、問題を確実に再現することが難しいため、この種のエラーのデバッグはストレスになる場合があります。

最も記憶に残るタイプのエラーの 1 つは、次のようなエラー メッセージを伴うものです。

ウォッチドッグが集合操作のタイムアウトを検出しました:WorkNCCL (SeqNum=408951、OpType=_ALLGATHER_BASE、…、タイムアウト (ms)=600000) は、タイムアウトするまでに 600351 ミリ秒実行されました

そして、トレーニング実行中のすべての GPU ワーカーがそのようなエラー メッセージを発行しました。

これは、1 つ以上のホストが NCCL 操作を完了できなかったか、NCCL と InfiniBand 接続がクラッシュしたため、NCCL_TIMEOUT タイムアウトに達するまで他のすべてのホストが同時にテンソル操作でスタックしたことを意味します。残念ながら、NCCL ソフトウェア ライブラリの性質上、どのホストに問題があるかを見つけるのは困難です。

NCCL ソフトウェア ライブラリのログにいくつかの変更を加えました。フォークされたバージョンを参照してください: https://github.com/boweiliu/nccl。これにより、クラッシュが発生したときに実行されているメッセージや操作がより明確になり、どのホストまたは GPU が実行を妨げているのかを特定できる可能性があります。

不正な動作をしているホストを特定するには、特定のログ メッセージを生成していないホストを特定する必要があることが多いことに注意してください。このようなメッセージがない場合は、このホスト上のワーカーが遅れているか、クラッシュしていることを示しています。

利用可能なエラー メッセージがないその他の応答しない状況は、通常、NVIDIA ドライバーまたは NVIDIA Docker 通信ドライバーのロックを引き起こす前述の Xid/SXid/ECC エラーなど、ハードウェア関連の問題に関連しています。 NCCL のハングをドライバーのハングや、Python コードの競合状態やデッドロックと区別するために、Py-Spy や GNU プロジェクト デバッガー (GDB) などのツールを使用して、発生した停止プロセスをリアルタイムでデバッグします。このアプローチを使用すると、1 つの特定の問題が発見されました。Python スレッド設定の構成エラーにより、一部のホストで 8 つのマルチスレッド NCCL GPU プロセスを正しく起動できず、PyTorch の前の初期化コード段階で競合状態が発生しました。

トレーニングの速度低下 (MFU によって測定)

ツールが不足しているため、この種の問題は以前の問題よりもさらにイライラさせられます。 Py-Spy、スタック トレース検査、GDB の使用に加えて、NVIDIA Nsight とプロファイリング ツールも採用しました。これらのツールの中には、高度に分散された設定では使用するのが難しいものもあります。

残念ながら、全体的な速度の低下や、以前に示したモデルの浮動小数点使用率 (MFU) よりも遅い速度には多くの理由が考えられます。

まず、構成、コード、環境変数を複数回チェックすると便利であることがわかりました。私たちが経験したエラーには、間違ったモデルの実行、間違ったバッチ サイズ、間違った UFM または NCCL 設定、CUDA_DEVICE_MAX_CONNECTIONS エラーなどがあります。これにより、最適なパフォーマンスが得られなくなります。

また、平滑化されていない MFU 曲線は問題クラスの診断に役立つことが多いため、(平滑化された平均やウィンドウ化された平均ではなく) 瞬間的な (つまり、バッチごとの) MFU を測定することも有用であることがわかりました。トレーニングの速度を低下させる原因となる問題には、次のようなものがあります。

非常に低い MFU (予想の 10 分の 1 未満) からトレーニングをすぐに開始し、安定した状態を維持します。

これは、T2 または T3 レイヤ スイッチのクラッシュなど、InfiniBand ネットワーク接続に関するハードウェアの問題である可能性が高くなります。 GPU と NIC の間のハードウェアの問題もこの状況を引き起こす可能性があり、その場合、dmesg は次のようなエラーを報告します: PCIe x16 レーンは次のように制限されています…

予想される MFU の 30% からすぐにトレーニングを開始し、安定して維持します

これは、1 つのホスト (NVIDIA ピア メモリ) 上の GDR 設定が間違っているか、GDR 環境変数が間違っていることが原因である可能性があります。

予想される MFU の約 60 ~ 80% から直ちにトレーニングを開始し、安定した状態を維持します。

最も一般的な原因は、InfiniBand リンクの品質が低いか障害があることです。具体的には、単一 GPU での InfiniBand NIC 関連の障害により、NCCL がネイティブ NVLink 経由でトラフィックをルーティングし、同じホスト上の別の GPU 上の NIC を使用しようとします。 CPU スロットリングによってもこの問題が発生する可能性があるため、一部のホストで BIOS 設定を調整する必要があります。

データの特定のバッチを処理するときに突然大幅な速度低下 (10 分の 1 の低下) が発生します。これは非常に頻繁に発生します。

これは基本的にチェックポイント設定または評価に関するものであり、エポック数またはステップ数をチェックすることで検証できます。厄介なことに、MFU が異常なときに自動アラームを設定すると、多くの誤ったアラームが表示されます。

特定のデータのバッチを処理するときに突然大幅な速度低下 (10 倍の低下) が発生する

これはランダムかつかなりまれに (15 分に 1 回程度) 発生し、その後すぐに良好な MFU に完全に戻ります。

最も一般的な原因は、CPU を集中的に使用する他のワークロードが実行中のホストにスケジュールされていることであるようです。特定のホストを識別するプロファイリング ツールを構築するよりも、PID によって CPU を大まかに監視する方が簡単であることがわかりました。原因は、データ ローダーのボトルネックなど、時折発生するネットワーク接続の問題である可能性があります。 NCCL 以外のコードのデータ ロード、チェックポイント、メトリクスを監視し、Python コードのタイミング ログを追加しました。これは非常に信頼性が高いことが証明されました。

MFU は動作中に徐々に速度が低下しますが、再起動するたびに 100% に戻ります。

理論的には、原因はスイッチの熱の蓄積である可能性がありますが、これが起こったことは一度もありません。ただし、Python と NVIDIA プロファイラーを使用して、パフォーマンス低下の原因が自動ガベージ コレクションであると思われることを確認しました。



これらの速度低下をデバッグすると、スループットが定期的にほぼ確実に低下することがわかりました。トレーニングが進むにつれて、この低下は分散コ​​ンピューティングへの影響を増大させるでしょう。このことから、ドロップの原因は自動ガベージ コレクションに関連しているのではないかと考えられ、この推測は分析とテストを通じて検証されました。すべてのホストで自動ガベージ コレクションを無効にし、特定の間隔でのみガベージ コレクションを設定すると、このスループットの「低下」は解消されました。

ZeRO-3 に基づく同期分散トレーニング アルゴリズム FSDP を使用しました。ブロッキング操作中に、ガベージ コレクションを実行する単一のワーカー プロセスにより、他のすべてのワーカーの速度が低下する可能性があります。ワーカー プロセスが数百ある場合、これにより大幅な速度低下が発生する可能性があります。

パフォーマンスは最初は良好ですが、その後突然 (予想の 70% まで) 低下し、高頻度で (15 秒ごと) 継続します。

これは、NVIDIA GPU の「クロック スロットルの理由」に関連していることがわかりました。これは、NVIDIA DCGM の適切な設定で解決できます。熱の問題 (GPU の温度が高いか、ホストの冷却ファンの障害/効率の低下) または電源の障害がこの問題を引き起こす可能性があります。また、CPU/RAM/ディスクとともに 8 つの GPU 使用率と 8x NIC InfiniBand 使用率をすべて最大にすると、特定の電源ハードウェアを備えた一部のホストで電圧の問題が発生しますが、それらをすべて使用するだけです (通常、これは実際のトレーニング実行)。

パフォーマンスは良好ですが、通常よりノイズが多くなります (予想される MFU の 90% と 100% の間の高周波ホワイト ノイズの分散)

これは InfiniBand ハードウェアにも関連していますが、通常は、T2 層への冗長性の低いホストではなく、ネットワークの上位リンクでのある程度のパフォーマンスの低下またはジッターが原因です。

残念ながら、これらの問題の多くは特定のホストを特定するのが難しく、InfiniBand スイッチ テクノロジのトポロジを認識する性質のため、InfiniBand 関連の問題は特に特定が困難です。 InfiniBand ファットツリー設計では、InfiniBand は隣接するホストを優先しているように見えますが、UFM は非対称リンク速度でパケットをルーティングできます。

以下は、スループットの問題をデバッグするための簡単な概要/フローチャート/完全性チェックリストです。

このシステムは以前は正常に動作していましたか?

最近どのような変更を加えましたか (コードのマージ、ドライバーの更新など)。

実行しているホストは健康ですか? Docker Hub、GitHub などのサードパーティ SaaS を含むすべての依存サービスは正常に実行されていますか?

現在実行しているコード、環境、構成、バージョン、ホスト リスト、ランキング順序、およびランダム シードが前回とまったく同じであることを確信できますか? (そのようなチェックが実装できれば。)

問題は再現可能ですか?

それは他のものとどのように関係するのでしょうか?他のプロセスは?毎日の crontab スケジュールされたタスク?ホスト、DCGM、または UFM インジケーター?

あなたのツールはこれらの指標を正しく測定していますか?

必要最低限​​のバージョンのコードを実行した場合 (より小さなモデル、偽のデータ、チェックポイントの保存や読み込みを行わない) を実行しても問題は解決しませんか?

インフラストラクチャツールの改善

上記の手順を完了すると、少なくとも何かが壊れるまでは、モデルをトレーニングするときに優れたパフォーマンスを達成できるようになります。

このセクションでは、理想的には人間の介入を可能な限り少なくしながら、一貫したトレーニングを保証するために使用されるツールとシステムのいくつかを紹介します。私たちは小規模なチームであるため、手動で修理を行うのに十分な人材がいないため、このプロセスも可能な限り自動化したいと考えています。

トレーニング中に遭遇するほとんどすべての問題は、マシンまたはネットワーク コンポーネントの障害に起因する可能性があります。このような種類の障害は大規模なクラスターでよく発生するため、私たちのアプローチは、障害が発生したマシンとネットワーク コンポーネントを自動的に無効にして、修復リクエストを送信することです。

機械の故障

実行がクラッシュした場合に、最新のチェックポイントから自動的に再起動するシステムを開発しました。この再起動プロセスでは、利用可能な各マシンが最初にヘルス チェックされ、次に合格したヘルス チェック結果に基づいて各マシンが分類され、最も健全なマシンでトレーニングを再開しようとします。

ネットワークコンポーネントの障害

私たちが観察したネットワーク障害はすべて UFM によって検出され、UFM イベント ログに記録されたため、対応は簡単でした。UFM ログを解析して適切なアクションを実行するだけでした。

UFM イベント システムは非常に複雑で、数十のイベント タイプが含まれています。ただし、実際には、問題となるイベントはほんのわずかで、主にリンク障害または高シンボル エラー手法に関連することがわかりました。これらのイベントを特定したら、UFM イベント ログを解析するスクリプトを作成し、最近のイベントに関連するリンクとポートを無効にし、これらのネットワーク コンポーネントのメンテナンス作業指示を要求し、メンテナンスの完了後にこれらのコンポーネントを再度有効にすることができます。

ローカルミラーファイルシステム

このような大規模な分散トレーニングでは、クラスターとイーサネット間のデータ交換の速度がボトルネックであることが長い間知られていました。共有イーサネット接続の帯域幅は約 10Gbit/秒ですが、数百人のワーカーがデータセットとモデル チェックポイントを同時にダウンロードすると、この帯域幅はすぐに飽和する可能性があります。

この目的を達成するために、クラウド ストレージのミラーとしてクラスター内にローカル ファイル システムを構築することにしました。これは本質的に、S3 から読み取られるファイルの量を削減できるキャッシュ スペースです。クラスターのチャーン (メンテナンス上の理由でマシンが無効になったり交換されたりする場合) を考慮して、各ファイルのコピーを 3 つ用意し、コンシステント ハッシュを使用して負荷を均等に分散し、クラスターのチャーン中のパフォーマンスを最大化して、ファイルの移動を大幅に削減します。クラスターのディスク容量は限られているため、ファイルのライフサイクルを追跡し、不要になったファイルを削除するツールを開発する必要がありました。

ローカル分散Dockerレジストリ

私たちは、Docker イメージをポイントツーポイントで転送するための優れたオープンソース ソフトウェアである Kraken を使用しました。ソフトウェアにはほとんど問題がありませんでしたが、タスクと実装の複雑さを考えると、これは私たちにとって非常に驚きでした。ツールのアドレス: https://github.com/uber/kraken

さまざまなパフォーマンス監視ツール

デフォルトのトーチ アナライザーと NVIDIA の Nsight システムをセットアップしました。後者は、順方向/逆方向のパスと NCCL 通信に必要な正確な時間を理解するのに役立ち、さらに、特定のモデル サイズとワーカーの数がボトルネックになるかどうかを判断するのに役立ちます。ただし、Nsight Systems は、Docker を特権モードで実行する必要があり、パフォーマンス監視イベントに関連するセキュリティ チェックを無効にする必要があり、構成を保存するにはトレーニング プロセス全体を停止する必要があることが多いため、使用するのが少し難しいです。

さらに、遅いトレーニング バッチを検出し、その考えられる原因を理解するためのツールを作成しました。これは便利だと思いました。最も便利なツールは、各バッチにかかる時間を監視し、バッチが遅すぎる場合はワーカーのスタック トレースを破棄します。これにより、軽微なハードウェアまたはソフトウェアの問題があるホストを簡単に見つけることができます。

マシンを異なるグループに分割して、障害が発生したホストを特定する

クラスターを使用し始めてから最初の数か月間 (ヘルスチェックが現在ほど徹底されていなかった頃)、マシンのグループでトレーニング中に障害が発生するという状況によく遭遇しましたが、どのマシンに問題があるのか​​は明らかではありませんでした。 。 質問。障害のあるホストを見つけるために、一連のマシンを異なるグループに分割し、マシンの各グループで小規模なトレーニングを実行することを容易にするツールを開発しました。

たとえば、48 台のマシンでのトレーニングの実行が失敗した場合は、それぞれ 8 台のマシンからなる 6 つのグループで小規模なトレーニングの実行を実行し、次にそれぞれ 6 台のマシンからなる 8 つのグループでより小さなトレーニングを実行します。通常、2 つのフェーズのうち 1 回の実行のみが失敗するため、両方のフェーズで失敗したマシンには障害があると確信して結論付けることができます。

反省と教訓

インフラストラクチャのセットアップと保守のプロセス中に、私たちはいくつかの有益な教訓を学びました。

有用なアプローチの 1 つは、マシンの場所を交換することです。実行時には、マシンに障害が発生した場合にトレーニングを簡単に再開できるように、必要なマシンより 10 ~ 20% 多くのマシンを使用すると便利です。各マシンが他のすべてのマシンに緊密に接続されるようにクラスタ ネットワークをセットアップすると、それらのマシンの動作中のサブセットを使用できるようになります。

トレーニング中に遭遇するすべての問題は再発するため、遭遇するすべてのハードウェアまたはソフトウェア障害に対してテストと自動化されたソリューションを作成することは有益です。同様に、あいまいなエラー メッセージごとに、エラーをより適切に説明するツールを作成する価値があります。

再現性は優れた科学研究の鍵です。私たちがすぐに採用した大きな原則の 1 つは、たとえ最も単純な事柄であっても、「一度に 1 つのことのみを変更する」というものでした。

信頼するだけでなく、検証することも必要です。外部ツールを導入したり、新しい人材を (社内外から) 招聘するときは常に、特に後続のステップがそれらの主張に依存している場合には、その主張を再確認します。

要約する

大規模な言語モデルをトレーニングするには、最初から複雑なインフラストラクチャが必要です。私たちがインフラストラクチャの設定の詳細に深く関与することを選択したのは、運用しているシステムを完全に理解することが重要であると考えており、そうすることがより効率的であると信じているからです。

このプロセスを経て、このアプローチを採用してよかったと思っています。インフラストラクチャを完全に制御し、あらゆる抽象化レベルで簡単にデバッグできる機能が重要な価値があることが証明されました。このプロセスには多くの監視と反復が必要でしたが、そのおかげで基礎となるワークフローを深く理解し、ホストの健全性を確保するためのツール セットを構築し、システムを自動化して継続的なスムーズなトレーニングを保証する方法を学び、最終的には最先端の言語モデルを迅速かつ反復的にトレーニングできるようにするインフラストラクチャのセット。

このインフラストラクチャ構築プロセスは、AI エージェントを研究および構築するための基本的な方法論を反映しています。つまり、詳細を調査し、既存のプロセスを継続的に改善し、意欲的なチームがより大きな課題に取り組むことを可能にする便利なツールとシステムを構築します。