Pythorchマシン学習モデルの性能を最大化する7つのテクニック!


(黒モードで読んでください.)
Hi! I'm Jaylnne. ✋
Facebookで公開されているFitochモデルを振り返る際、GPU環境に触れずにモデル性能を向上させる方法はありますか?こんな好奇心が生まれた.そんな方法はないと思います.案の定、グーグル検索の結果、1つの文章がきれいに整理されているので、簡単に、簡単に、韓国語で整理したいと思っています.
非専門家のML/DLは見知らぬ開発者にも理解してもらうために多くの解釈をするので、憂鬱な人は直接次の原文を読むことができます.
👇👇👇
[Towardsdatascience] 7 tips for squeezing maximum performance from pytorch
著者はWilliamFalconで、著者のプロフィールからFacebookでAI研究員であることがわかります.pytorchはFavousが開発した深い学習フレームワークなので、文章の内容はかなり信頼できるはずです.
今、文章の内容を正式に整理します.
ああ!その前に,pytorch稲妻をベースに説明したほうがよい.pytorch稲妻が何なのか分からない人には、以下のように簡単に説明します.

Pythorch Lightingとは?



簡単に言えばテンソル流のkerasのような存在と言える.これはpytorchをより使いやすくするためのツールです.以下の画像のように、Pythorchコードは表示と編集が容易な簡潔性があり、より簡単なコードを書くことで、モデル学習、テスト、検証、分散GPU/CPU設定などを行うことができます.

7 Tips 💡


今から本当に始めましょう.

1. User workers in DataLoaders

DataLoader(dataset, num_workers=8)
DataLoadersは労働者の使用を要求した.に傷をつける🤔 だから直訳すると、データをロードする機能の中で、スタッフ(?)利用という意味です.もう少し考えてみましょう.コンピューターで働く労働者は過程を指すべきだ.彼はデータのロードを担当するスタッフで、データのロードを担当するプロセスです.
しかし、ここでは労働者たちの使用を要求しています.すなわち,複数のプロセスを同時に向上させることができる.アクリハ-したがって、データ・ロード中にアップロードする複数のプロセスを設定します.オプションの名前はnum workerかもしれません.
👀 だから何人かの労働者、いいえ、num workersをいくらにしますか?
記事では、私のパソコンで使用するGPUの数に4を乗じた値を推奨します.
✅ num_workers= 4 * num_GPU
もちろん「おすすめ」で、「必須」ではありません.自分の開発環境に合わせて適宜調整すればよい.

2. Pin memory

DataLoader(dataset, pin_memory=True)
今回も直訳から始めましょう固定メモリ?に傷をつけるどういう意味ですか.
例を挙げる.レストランなら、私たちのグループの会食のために、レストランのテーブルを予約しました.実際、チームメンバーが到着するとテーブルの位置が残るかもしれませんが、いずれにしてもレストランのオーナーは予約したテーブルを他のお客さんに渡すことはできません.ここで、「レストランのテーブルを予約」は「pin memoryをtrueに設定」です.
では、レストランは何ですか.テーブルは何ですか.
✅ 식당: CPU, 테이블: GPU와 통신하기 위한 CPU의 메모리 공간
GPUにデータを転送するには、GPUと通信する必要があります.この通信を担当するプロセスにはもちろんCPUメモリも必要です.これは、CPUとGPUとの間で無条件に一定量以上の通信メモリを保持することを意味する.

👀 でもどうしてそうすればいいの?
pin memoryを有効にすると、CPUがGPUにデータを転送する速度が速くなるため、pytorchフォーラムコミュニティの記事を見ました.したがって、データが速度差がない程度小さい場合や、最初からGPUにデータをロードする場合は、どうでもいい.

3. Avoid CPU to GPU transfers or vice-versa

# BAD
.cpu()
.item()
.numpy()

# GOOD
.detach()
CPUとGPU間でのデータ転送を回避し,推奨と非推奨を区別する方法が求められる.
BADに相当するコードは、CPUにデータをアップロードする役割を果たす.pin memoryの説明では,CPUからGPUへのデータ転送にも時間がかかることが予想される.そこで、GPUデータをCPUの関連コードに転送することを推奨します.△もちろん、これは使わないということではなく、あまり使わないということです.
逆に、GOODに対応したコードを使うのがおすすめです.モデルが学習中に逆伝播に使用される計算グラフィックを除去する場合.説明detach()コードを使用します.

4. Construct tensors directly on GPU

# BAD
t = tensor.rand(2, 2).cuda()

# GOOD
t = tensor.rand(2, 2, device=torch.device('cuda'))
3番目のヒントで述べたように、CPUとGPUの間でデータを転送すると、多くの速度が低下します.最善の方法はGPUに直接データをロードすることです今回著者らは,マッピングコードと推奨コードも明確に示した.以降は#BAD方式よりも#GOOD方式でのコード作成に注意する.

5. Use DistributedDataParallel not DataParallel


5つ目のヒントは、1つのGPUではなく複数のGPUを使用する場合に役立つ方法です.間違いなく、直訳から、DataParallel(DP)ではなく、分散型Parellel(DDP)が使用される.に傷をつけるDPとDDPが何なのかを知ることで理解できる
文章で説明した内容だけではわかりにくいので、追加でGoogle検索を行いました.簡単に言えば、DP方式はマルチスレッドであり、DDP方式はマルチプロセッシングである.では、マルチスレッドは何なのか、マルチプロセッサは何なのか.二つの違いは何ですか.
まず、プロセス(process)は、タスクを実行するために厳密にはコマンドリスト(より正確にはメモリリスト)である.また、このコマンドリストの各コマンドを実行する実際のオペレータはスレッドである.
したがって、マルチスレッドは1つのプロセスを意味し、そのプロセス命令を実行するスレッドは複数であり、マルチプロセスは複数のプロセスを意味し、各プロセスは1つのスレッドを実行する.
# DP
Trainer(distributed_backend='dp', gpus=8)

# DDP
Trainer(distributed_backend='ddp', gpus=8)
pytorch lightningを使用する場合、上記の例のようにコードは非常に簡単です.
👀 しかし、なぜマルチプロセッサDDP方式がマルチスレッドDP方式よりも速いのでしょうか.
答えはPythonのグローバルプリフェッチロック(GIL)にある.分からない用語が出たからといって慌ててはいけない.ロックという言葉が含まれているので、何をしないように「ロック」機能であるべきです.何をさせないのですか.複数のスレッドが同時に動作するのを阻止する機能と考えられる.したがって、python言語ベースのpytorchは、DP方式ではなくDDP方式を推奨する.

6. Use 16-bit precision


6つ目のテクニックは、32ビットからなるデータを16ビットに変換して使用することです.32ビットデータを16ビットに変換すると、データの消費メモリが半分に減少します.これにより、モデル学習のレイアウト寸法を2倍に拡大し、学習速度をより速く向上させることができる.
さらに,特定のGPUモデル(C 100080 TI)も16−bit計算に特化している.このため、32ビット計算を行う場合と比較して、16ビットデータを計算する場合、速度を3倍から8倍に向上させることができる.🙌
Trainer(precision=16)
また、pytorch lightningを使用して簡単に設定することもできます.
Note) pytorch 1.6 이전 버전에서는 Nvidia Apex 도 함께 설치해주어야 한다. 하지만 그 이후 버전에서는 pytorch ligntning 을 사용할 때 자동으로 pytorch 버전을 인식해 32-bit 로 진행할지 16-bit 로 진행할지 결정해 준다고 한다.

7. Profile your code


最後のヒントは「コードを構成する」です.プロファイルとは詳細な分析と呼ばれ、実行されたプロセスがどのように実行されているかを示します.各作業にどれくらいの時間がかかるか、どれだけのメモリが消費されるかなど、モデルの学習速度が遅すぎると判断した場合、このプロファイルを使用すると、ボトルネックを簡単に見つけることができます.
Trainer(profile=True)
上記のコードのようにprofileをアクティブにすると、下図に示す結果が得られます.

実際、上記の結果はpytorch lightningに内蔵されたコンパイラによって起動された結果です.もしそうなら、他のプログラムを起動することもできます.
たとえば、
profiler = AdvancedProfiler()
Trainer(profiler=profiler)
このように異なるタイプのアナライザを指定すると、次のような異なる形式の結果が得られる場合があります.

間違った内容があればコメントで教えてください🙇‍♀️