Accelerate documentation
Accelerateの内部メカニズム
Accelerateの内部メカニズム
内部では、Accelerate はスクリプトが起動された環境を分析し、どの種類の分散セットアップが使用されているか、いくつの異なるプロセスが存在するか、現在のスクリプトがそのうちのどれに属しているかを判定します。これらの情報はすべて ~AcceleratorState に保存されます。
このクラスは、~Acceleratorを初めてインスタンス化するとき、および分散環境のセットアップに必要な特定の初期化を実行するときに初期化されます。その後、その状態はAcceleratorStateのすべてのインスタンス間で一意に共有されます。(これと同様の処理は、よりシンプルなバージョンである継承元のPartialStateでも実行できます)
その後、prepare()を呼び出すと、ライブラリは以下を行います:
- 分散環境に適応したコンテナでモデルをラップします。
- オプティマイザーをAcceleratedOptimizerでラップします。
- スケジューラをAcceleratedSchedulerでラップします
- creates a new version of your dataloader(s) in a DataLoaderShard or DataLoaderDispatcher
モデル、オプティマイザー、スケジューラーは単純なラッパーに格納されるだけですが、データローダーは再作成されます。これは主に、PyTorchでは一度作成されたデータローダーのbatch_samplerを変更できないためであり、ライブラリはbatch_samplerを変更してnum_processes個のバッチごとに1つずつ(有効な場合)生成させることで、プロセス間のデータシャーディングを処理するためです。
DataLoaderShardはDataLoaderをサブクラス化し、以下の機能を追加します。
- 各新しいイテレーションにおいて、すべてのプロセスの適切な乱数生成器を同期させ、シャッフルなどのランダム化がプロセス間で完全に同じ方法で実行されることを保証します。
device_placement=Trueを無効にしない限り、バッチをイールドする前に適切なデバイスに配置します。
DataLoaderDispatcherのサブクラスは、DataLoaderを反復する際に、データがプロセス0から開始され、その後分割されて各プロセスに送信される点で、DataLoaderShardとは異なります。これは、データセットレベルで分割が行われるのとは対照的です。
乱数生成器の同期は、デフォルトで以下を同期します:
- PyTorch >= 1.6 における、特定のサンプラー(PyTorch の
RandomSamplerなど)のgenerator属性 - PyTorch <=1.5.1のメインな乱数生成器
メインのAcceleratorのrng_types引数で、同期させる乱数生成器を選択できます。PyTorch >= 1.6 では、すべてのプロセスでメインの乱数生成器に同じシードを設定することを避けるため、ローカルのgeneratorに依存することをお勧めします。
メインのtorch(またはCUDA、XLA)乱数生成器の同期は、データセットに存在する他の潜在的な乱数由来の要素(ランダムなデータ拡張など)にも影響を及ぼします。具体的には、すべてのプロセスがtorchの乱数モジュールから同じ乱数を取得するため、torchによって制御されている場合、同じランダムなデータ拡張が適用されます。
カスタムサンプラー、バッチサンプラー、またはイテラブルデータセットのランダム化部分は、PyTorch >= 1.6 のローカル
torch.Generatorオブジェクトを使用して行われるべきです。例として、従来のRandomSamplerを参照してください。
torchdata>=0.8.0 がインストールされており、DataLoaderConfiguration に use_stateful_dataloader=True を渡している場合、これらのクラスは代わりに StatefulDataLoader を直接継承し、state_dict を保持します。
内部の詳細については、Internalsページを参照してください。
Update on GitHub