1兆のパラメーターモデルのトレーニングに向けたメモリ最適化」で紹介されているゼロDPの実装です。オプティマイザの状態、グラデーション、パラメータの断片を複数のデバイス/ノードに保持します。これにより、メモリ消費量が元のモデルと同じになります。ここで、Ψはパラメーターの数、Nd​はシャードの数、Kパラメーターごとのオプティマイザーのバイト数です。ビットの精度を前提としたパラメーターとグラデーションのメモリです。オプティマイザー用です。つのモーメントを保持しているためです。残留メモリ消費を対象とするゼロRメモリ最適化は実装しておらず、DPがゼロの部分のみを実装しています。この実装では、パラメータのサブセットのみのトレーニングをサポートしています。この実装はフェアスケールFSDPに触発されています。NeoXを微調整するスクリプトを次に示します。レイヤーモデルの各レイヤー(またはいくつかの連続したレイヤーの組み合わせ)をこのモジュールでラップする必要があります。各シャードはパラメータをリストに保持します。固定パラメーター用です。これはリスト内のチャンクのサイズです。List[int]#最初のチャンクはトレーニング可能なパラメーター用です。0#これは、トレーニング可能なパラメーターと固定パラメーターとしてリストに分割されたパラメーターのリストです。List['Zero3Layer']#現在のレイヤーの位置。ラップするモジュール。現在のノードのランク。データがシャーディングされるノード/デバイスの数。レイヤーのデータタイプ。torch.no_grad():#レイヤーのすべてのパラメーターを収集します。self.parameters()]#パラメータの形状を保存しておきます。後で再構築する必要があるからです。ノードは、各デバイス/ノードが保存するサイズを計算し、それに応じてパラメータを分散します。self._cleanup_params()#後方フックを追加。これは、モジュールを基準としたグラデーションが計算されるときに呼び出されます。次の数で割り切れるようにパディングします。self._empty((padding_fixed,))#すべてのパラメータを連結してパディングします。dim=0)#トレーニング可能なパラメータのチャンク/シャードを取得します。これを現在のノードのオプティマイザーに渡します。[self.chunk[self.TRAINING_PARAMS_IDX]]#与えられた形状の空のテンソルを作成します。dtype=self.dtype)#パラメータデータをクリーンアップするこれにより、レイヤーパラメーターで使用されていたすべてのメモリが解放されます。_cleanup_params(self):#パラメータがフェッチされないことを示すフラグを設定します。ps:#パラメータの操作が完了するまで待ってから、新しい操作を行います。storage."#ストレージのサイズをに変更します。0これにより、パラメータが使用していたメモリが解放されます。グラフはメモリへの参照を保持するので、設定してもメモリは解放されません。None'#すべてのシャードからパラメータを取得これにより、すべてのノードからすべてのパラメータデータが取得され、各ノードのパラメータが再構築されます。True#取得または共有するものがない場合はスキップしてください。使用してすべてのシャードからパラメータを取得します。sum(self.chunk_size),))#連続バッファをノード数に分割します。これらの分割は「buffer」のビューです。dim=1)#収集操作が完了するのを待ってから、バッファへの参照をクリアします。ignore[attr-defined]#パラメータのストレージサイズを変更します。これは、0パラメータをクリーンアップしたときに設定されました。**kwargs):#現在のノードのすべてのパラメータを取得します。これは前のレイヤーから呼び出されるので、この呼び出しはパラメーターがフェッチされていることを確認するためだけのものです。self.fetch_params()#パラメータの取得が完了するまでお待ちください。torch.cuda.current_stream().wait_stream(self.fetch_stream)#処理中のレイヤーのパラメーターの取得を開始します。すれば、現在のレイヤーが計算を行うパラメーターが取得されます。有効になっている場合は、現在のレイヤーのパラメーターに逆方向フックを追加します。**kwargs)#レイヤーのパラメーターをクリーンアップします。有効になっていて、これがネットワークの最後のレイヤーである場合は、後方パスのパラメーターを再度取得する必要があるため、クリーンアップをスキップしてください。res#現在のレイヤーのパラメーターに逆方向フックを追加します。p.expand_as(p)#後ろ向きフックを取り付けるためのハンドルを用意してください。ついて説明しますgrad_acc。1#逆方向イベントの処理これは、パラメーターの逆方向フックとモジュールの逆方向フックによって呼び出されます。呼び出されたら、グラデーションをバックアップしてパラメータをクリーンアップできます。次にそのレイヤーのグラデーションを処理するので、前のレイヤーのパラメーターの取得を開始します。self._backward_event()#前のレイヤーがグラデーションの計算を開始します。パラメータの取得が完了したことを確認する必要があります。self.chunk_size[self.TRAINING_PARAMS_IDX],))#連続バッファを複数のノードに分割します。これらの分割は「buffer」のビューです。self._empty((self.chunk_size[self.TRAINING_PARAMS_IDX],))#各シャードのグラデーションを累積します。バッファをノード全体に分散させ、各ノードは受け取ったテンソルを蓄積(削減)します。buffers)#操作が完了するのを待ってから、バッファへの参照をクリアします。buffers#チャンクのグラデーションを設定します。これがオプティマイザーの見解です。