Pytorch中的分布式神經網絡訓練|pytorch|bat|拆分|調用_網易訂閱

2021-01-08 網易

  隨著深度學習的多項進步,複雜的網絡(例如大型transformer 網絡,更廣更深的Resnet等)已經發展起來,從而需要了更大的內存空間。 經常,在訓練這些網絡時,深度學習從業人員需要使用多個GPU來有效地訓練它們。 在本文中,我將向您介紹如何使用PyTorch在GPU集群上設置分布式神經網絡訓練。

  

  通常,分布式訓練會在有一下兩種情況。

  1. 在GPU之間拆分模型:如果模型太大而無法容納在單個GPU的內存中,則需要在不同GPU之間拆分模型的各個部分。

  1. 跨GPU進行批量拆分數據。當mini-batch太大而無法容納在單個GPU的內存中時,您需要將mini-batch拆分到不同的GPU上。

跨GPU的模型拆分

  跨GPU拆分模型非常簡單,不需要太多代碼更改。 在設置網絡本身時,可以將模型的某些部分移至特定的GPU。 之後,在通過網絡轉發數據時,數據也需要移動到相應的GPU。 下面是執行相同操作的PyTorch代碼段。

  from torch import nn
class Network(nn.Module):
def __init__(self, split_gpus=False):
super().__init__()
self.module1 = ...
self.module2 = ...
self.split_gpus = split_gpus
if split_gpus: #considering only two gpus
self.module1.cuda(0)
self.module2.cuda(1)
def forward(self, x):
if self.split_gpus:
x = x.cuda(0)
x = self.module1(x)
if self.split_gpus:
x = x.cuda(1)
x = self.module2(x)
return x

跨GPU的數據拆分

  有3種在GPU之間拆分批處理的方法。

  · 積累梯度

  · 使用nn.DataParallel

  · 使用nn.DistributedDataParallel

積累梯度

  在GPU之間拆分批次的最簡單方法是累積梯度。 假設我們要訓練的批處理大小為256,但是一個GPU內存只能容納32個批處理大小。 我們可以執行8(= 256/32)個梯度下降迭代而無需執行優化步驟,並繼續通過loss.backward()步驟添加計算出的梯度。 一旦我們累積了256個數據點的梯度,就執行優化步驟,即調用optimizer.step()。 以下是用於實現累積漸變的PyTorch代碼段。

  TARGET_BATCH_SIZE, BATCH_FIT_IN_MEMORY = 256, 32
accumulation_steps = int(TARGET_BATCH_SIZE / BATCH_FIT_IN_MEMORY)
network.zero_grad() # Reset gradients tensors
for i, (imgs, labels) in enumerate(dataloader):

preds = network(imgs) # Forward pass
loss = loss_function(preds, labels) # Compute loss function
loss = loss / accumulation_steps # Normalize our loss (if averaged)
loss.backward() # Backward pass
if (i+1) % accumulation_steps == 0: # Wait for several backward steps
optim.step() # Perform an optimizer step
network.zero_grad() # Reset gradients tensors

  優點: 不需要多個GPU即可進行大批量訓練。 即使使用單個GPU,此方法也可以進行大批量訓練。

  缺點: 比在多個GPU上並行訓練要花費更多的時間。

使用nn.DataParallel

  如果您可以訪問多個GPU,則將不同的批處理拆分分配給不同的GPU,在不同的GPU上進行梯度計算,然後累積梯度以執行梯度下降是很有意義的。

  

  多GPU下的forward和backward

  基本上,給定的輸入通過在批處理維度中分塊在GPU之間進行分配。 在前向傳遞中,模型在每個設備上複製,每個副本處理批次的一部分。 在向後傳遞過程中,將每個副本的梯度求和以生成最終的梯度,並將其應用於主gpu(上圖中的GPU-1)以更新模型權重。 在下一次迭代中,主GPU上的更新模型將再次複製到每個GPU設備上。

  在PyTorch中,只需要一行就可以使用nn.DataParallel進行分布式訓練。 該模型只需要包裝在nn.DataParallel中。

  model = torch.nn.DataParallel(model)
...
...
loss = ...
loss.backward()

  優點:並行化多個GPU上的NN訓練,因此與累積梯度相比,它減少了訓練時間。因為代碼更改很少,所以適合快速原型製作。

  缺點:nn.DataParallel使用單進程多線程方法在不同的GPU上訓練相同的模型。 它將主進程保留在一個GPU上,並在其他GPU上運行不同的線程。 由於python中的線程存在GIL(全局解釋器鎖定)問題,因此這限制了完全並行的分布式訓練設置。

使用DistributedDataParallel

  與nn.DataParallel不同,DistributedDataParallel在GPU上生成單獨的進程進行多重處理,並利用GPU之間通信實現的完全並行性。但是,設置DistributedDataParallel管道比nn.DataParallel更複雜,需要執行以下步驟(但不一定按此順序)。

  將模型包裝在torch.nn.Parallel.DistributedDataParallel中。

  設置數據加載器以使用distributedSampler在所有GPU之間高效地分配樣本。 Pytorch為此提供了torch.utils.data.Distributed.DistributedSampler。設置分布式後端以管理GPU的同步。 torch.distributed.initprocessgroup(backend ='nccl')。

  pytorch提供了用於分布式通訊後端(nccl,gloo,mpi,tcp)。根據經驗,一般情況下使用nccl可以通過GPU進行分布式訓練,而使用gloo可以通過CPU進行分布式訓練。在此處了解有關它們的更多信息https://pytorch.org/tutorials/intermediate/dist_tuto.html#advanced-topics

  在每個GPU上啟動單獨的進程。同樣使用torch.distributed.launch實用程序功能。假設我們在群集節點上有4個GPU,我們希望在這些GPU上用於設置分布式培訓。可以使用以下shell命令來執行此操作。

  python -m torch.distributed.launch --nproc_per_node=4
--nnodes=1 --node_rank=0
--master_port=1234 train.py

  在設置啟動腳本時,我們必須在將運行主進程並用於與其他GPU通信的節點上提供一個空閒埠(在這種情況下為1234)。

  以下是涵蓋所有步驟的完整PyTorch要點。

  import argparse
import torch
from torch.utils.data.distributed import DistributedSampler
from torch.utils.data import DataLoader
#prase the local_rank argument from command line for the current process
parser = argparse.ArgumentParser()
parser.add_argument("--local_rank", default=0, type=int)
args = parser.parse_args()
#setup the distributed backend for managing the distributed training
torch.distributed.init_process_group('nccl')
#Setup the distributed sampler to split the dataset to each GPU.
dist_sampler = DistributedSampler(dataset)
dataloader = DataLoader(dataset, sampler=dist_sampler)
#set the cuda device to a GPU allocated to current process .
device = torch.device('cuda', args.local_rank)
model = model.to(device)
model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[args.local_rank],
output_device=args.local_rank)
#Start training the model normally.
for inputs, labels in dataloader:
inputs = inputs.to(device)
labels = labels.to(device)
preds = model(inputs)
loss = loss_fn(preds, labels)
loss.backward()
optimizer.step()

  請注意,上述實用程序調用是針對GPU集群上的單個節點的。 此外,如果要使用多節點設置,則必須在選擇啟動實用程序時選擇一個節點作為主節點,並提供master_addr參數,如下所示。 假設我們有2個節點,每個節點有4個GPU,第一個IP位址為「 192.168.1.1」的節點是主節點。 我們必須分別在每個節點上啟動啟動腳本,如下所示。

  在第一個節點上運行

  python -m torch.distributed.launch --nproc_per_node=4 --nnodes=1 --node_rank=0--master_addr="192.168.1.1" --master_port=1234 train.py

  在第二個節點上,運行

  python -m torch.distributed.launch --nproc_per_node=4 --nnodes=1 --node_rank=1--master_addr="192.168.1.1" --master_port=1234 train.py

  其他實用程序功能:

  在評估模型或生成日誌時,需要從所有GPU收集當前批次統計信息,例如損失,準確率等,並將它們在一臺機器上進行整理以進行日誌記錄。 PyTorch提供了以下方法,用於在所有GPU之間同步變量。

  1. torch.distributed.gather(inputtensor,collectlist,dst):從所有設備收集指定的inputtensor並將它們放置在collectlist中的dst設備上。

  1. torch.distributed.allgather(tensorlist,inputtensor):從所有設備收集指定的inputtensor並將其放置在所有設備上的tensor_list變量中。

  1. torch.distributed.reduce(inputtensor,dst,reduceop = ReduceOp.SUM):收集所有設備的input_tensor並使用指定的reduce操作(例如求和,均值等)進行縮減。最終結果放置在dst設備上。

  1. torch.distributed.allreduce(inputtensor,reduce_op = ReduceOp.SUM):與reduce操作相同,但最終結果被複製到所有設備。

  有關參數和方法的更多詳細信息,請閱讀torch.distributed軟體包。 https://pytorch.org/docs/stable/distributed.html

  例如,以下代碼從所有GPU提取損失值,並將其減少到主設備(cuda:0)。

  #In continuation with distributedDataParallel.py abovedef get_reduced_loss(loss, dest_device):
loss_tensor = loss.clone()
torch.distributed.reduce(loss_tensor, dst=dest_device)
return loss_tensorif args.local_rank==0:
loss_tensor = get_reduced_loss(loss.detach(), 0)
print(f'Current batch Loss = {loss_tensor.item()}'優點:相同的代碼設置可用於單個GPU,而無需任何代碼更改。 單個GPU設置僅需要具有適當設置的啟動腳本。

  缺點: BatchNorm之類的層在其計算中使用了整個批次統計信息,因此無法僅使用一部分批次在每個GPU上獨立進行操作。 PyTorch提供SyncBatchNorm作為BatchNorm的替換/包裝模塊,該模塊使用跨GPU劃分的整個批次計算批次統計信息。 請參閱下面的示例代碼以了解SyncBatchNorm的用法。

  network = .... #some network with BatchNorm layers in itsync_bn_network = nn.SyncBatchNorm.convert_sync_batchnorm(network)
ddp_network = nn.parallel.DistributedDataParallel(
sync_bn_network,
device_ids=[args.local_rank], output_device=args.local_rank)

總結

  · 要在GPU之間拆分模型,請將模型拆分為submodules,然後將每個submodule推送到單獨的GPU。

  · 要在GPU上拆分批次,請使用累積梯度nn.DataParallel或nn.DistributedDataParallel。

  · 為了快速進行原型製作,可以首選nn.DataParallel。

  · 為了訓練大型模型並利用跨多個GPU的完全並行訓練,應使用nn.DistributedDataParallel。

  · 在使用nn.DistributedDataParallel時,用nn.SyncBatchNorm替換或包裝nn.BatchNorm層。

  作者:Nilesh Vijayrania

  deephub翻譯組

特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺「網易號」用戶上傳並發布,本平臺僅提供信息存儲服務。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相關焦點

  • Pytorch中的分布式神經網絡訓練
    隨著深度學習的多項進步,複雜的網絡(例如大型transformer 網絡,更廣更深的Resnet等)已經發展起來,從而需要了更大的內存空間。 經常,在訓練這些網絡時,深度學習從業人員需要使用多個GPU來有效地訓練它們。 在本文中,我將向您介紹如何使用PyTorch在GPU集群上設置分布式神經網絡訓練。通常,分布式訓練會在有一下兩種情況。
  • PyTorch 0.2發布:更多NumPy特性,高階梯度、分布式訓練等
    這一版本引入了NumPy風格的Broadcasting、Advanced Indexing,增加了高階梯度和分布式PyTorch。PyTorch的GitHub新版發布說明中介紹了0.2版的以下新特性:NumPy風格的Tensor BroadcastingBroadcasting是NumPy在算數運算中處理不同形狀數組的一種方式,在特定條件下,比較小的數組會通過比較大的數組進行「廣播」,來獲得相應的形狀。
  • PyTorch 1.7發布,支持CUDA 11、Windows分布式訓練
    該版本增添了很多新特性,如支持 CUDA 11、Windows 分布式訓練、增加了支持快速傅立葉變換(FFT)的新型 API 等。PyTorch 1.7 版本包含很多新的 API,如支持 NumPy 兼容的 FFT 操作、性能分析工具,以及對基於分布式數據並行(DDP)和基於遠程過程調用(RPC)的分布式訓練的重要更新。
  • PyTorch中使用DistributedDataParallel進行多GPU分布式模型訓練
    這篇文章是使用torch.nn.parallel.DistributedDataParallel API在純PyTorch中進行分布式訓練的簡介。 我們會:討論一般的分布式訓練方式,尤其是數據並行化涵蓋torch.dist和DistributedDataParallel的相關功能,並舉例說明如何使用它們測試真實的訓練腳本,以節省時間什麼是分布式訓練?
  • PyTorch上也有Keras了,訓練模型告別Debug,只需專注數據和邏輯
    魚羊 發自 凹非寺量子位 報導 | 公眾號 QbitAI在開始一個新的機器學習項目時,難免要重新編寫訓練循環,加載模型,分布式訓練……然後在Debug的深淵裡看著時間譁譁流逝,而自己離項目核心還有十萬八千裡。
  • 重磅| Torch7團隊開源PyTorch:Python優先的深度學習框架
    動態神經網絡:基於 tape 的 autogradPyTorch 有一種獨特的神經網絡構建方法:使用和重放 tape recorder。TensorFlow、Theano、Caffe 和 CNTK 等大部分框架對世界的視角都是靜態的,讓人們必須先構建一個神經網絡,然後一次又一次地使用同樣的結構;如果要想改變該網絡的行為,就必須完全從頭開始。
  • 初學AI神經網絡應該選擇Keras或是Pytorch框架?
    keras是神經網絡的一個模型計算框架,嚴格來說不是神經網絡框架。本身沒有重量級計算,它使用其他AI框架作為計算後臺,傻瓜式的使用。它的計算後臺還支持 Theano、CNTK(微軟的一個AI計算後臺)等,也就是說keras是多個計算後臺的門面。官方設計哲學為Simple. Flexible.
  • PyTorch框架歷史和特性更迭與安裝過程
    PyTorch 0.4是在PyTorch 1.0之前的最後一個大版本,在PyTorch 0.4.0中,相對前一個版本而言,對分布式計算的支持更加完善,方便了用戶的使用。同時,ONNX也增加了對循環神經網絡(Recurrent Neural Network,RNN)的支持。
  • PyTorch 1.6來了:新增自動混合精度訓練、Windows版開發維護權移交...
    總的來說,PyTorch 1.6 版本包括許多新的 API、用於性能改進和性能分析的工具,以及對基於分布式數據並行(DDP)和遠程過程調用(RPC)的分布式訓練的重大更新。一些亮點包括:在英偉達的幫助下增加了對自動混合精度(AMP)訓練的本地支持,並且具有穩定的功能;增加了對 TensorPipe 的本地支持;在前端 API 增加了對複雜張量的支持;提供張量級內存消耗信息的新分析工具;分布式數據並行(DDP)訓練和遠程過程調用(RPC
  • PyTorch最新:分布式模型並行、Java程序、移動端等多項新功能
    本次更新的重點是增加了很多重要的新特性,包括給用戶提供 Build 級別的移動端定製化支持、增加分布式模型並行訓練、讓 Java 程序能夠運行 TorchScript 等。此外還有 JIT、C++、分布式訓練、Eager 前端、PyTorch Mobile 等方面的功能改進和 Bug 修復。
  • 大家心心念念的PyTorch Windows官方支持來了
    GitHub 發布地址:https://github.com/pytorch/pytorch/releasesPyTorch 官網:http://pytorch.org/當然除了 Windows 支持外,0.4.0 版的 PyTorch 還重點權衡了計算中的內存、支持多種概率分布、優化數據類型和修正張量等。機器之心也嘗試在 Windows 安裝簡單的 CPU 版,如下所示我們使用 pip 可以非常輕鬆而流暢地安裝 PyTorch。
  • PyTorch最新:支持分布式模型並行、Java程序、移動端等多項新功能
    本次更新的重點是增加了很多重要的新特性,包括給用戶提供 Build 級別的移動端定製化支持、增加分布式模型並行訓練、讓 Java 程序能夠運行 TorchScript 等。此外還有 JIT、C++、分布式訓練、Eager 前端、PyTorch Mobile 等方面的功能改進和 Bug 修復。
  • PyTorch 0.4:完全改變API,官方支持Windows
    >遷移指南新功能張量全面支持高級索引快速傅立葉變換神經網絡權衡內存計算bottleneck - 一個在你的代碼中識別hotspots的工具torch.distributions24個基本概率分布分布式訓練易於使用的Launcher utilityNCCL2後端C ++擴展Windows支持ONNX改進RNN支持性能改進Bug修復主要核心變化以下是用戶每天使用的最重要的核心功能的更新
  • 《PyTorch中文手冊》來了
    PyTorch 深度學習:60 分鐘快速入門 (官方)張量Autograd: 自動求導神經網絡訓練一個分類器選讀:數據並行處理 (第二章 基礎第一節 PyTorch 基礎張量自動求導神經網絡包神經網絡簡介第四節 卷積神經網絡卷積神經網絡
  • 還不會使用PyTorch框架進行深度學習的小夥伴,看過來
    Pytorch 的張量Pytorch Autograd 機制Pytorch 的 nn 模塊Pytorch optim 包Pytorch 中的自定義 nn 模塊總結和延伸閱讀何為深度學習?深度學習是機器學習的一個子領域,其算法受到了人類大腦工作機制的啟發。這些算法被稱為人工神經網絡。這樣的神經網絡包括用於圖像分類的卷積神經網絡、人工神經網絡和循環神經網絡。
  • 60分鐘入門深度學習工具PyTorch
    autograd包.我們首先簡單介紹一下這個包,然後訓練我們的第一個神經網絡.完成計算後,您可以調用.backward並自動計算所有梯度。此張量的梯度將累積到.grad屬性中。要阻止張量跟蹤歷史記錄,可以調用.detach將其從計算歷史記錄中分離出來,並防止將來的計算被跟蹤。
  • 代碼詳解:用Pytorch訓練快速神經網絡的9個技巧
    估計你還在用32位精度或*GASP(一般活動仿真語言)*訓練,甚至可能只在單GPU上訓練。如果市面上有99個加速指南,但你可能只看過1個?(沒錯,就是這樣)。但這份終極指南,會一步步教你清除模型中所有的(GP模型)。不要讓你的神經網絡變成這樣。(圖片來源:Monsters U)這份指南的介紹從簡單到複雜,一直介紹到你可以完成的大多數PITA修改,以充分利用你的網絡。
  • 雲計算學習:用PyTorch實現一個簡單的分類器
    主要流程分為以下三個部分:1,自定義生成一個訓練集,具體為在二維平面上的一些點,分為兩類;2,構建一個淺層神經網絡,實現對特徵的擬合,主要是明白在 pytorch 中網絡結構如何搭建;3,完成訓練和測試部分的工作,熟悉 pytorch 如何對網絡進行訓練和測試。1.
  • 一行代碼安裝,TPU也能運行PyTorch,修改少量代碼即可快速移植
    pip install pytorch-lightning該項目的開發者William Falcon說,PyTorch Lightning是他在紐約大學和FAIR做博士生時研發,專門為從事AI研究的專業研究人員和博士生創建的。
  • Pytorch-Transformers 1.0 發布,支持六個預訓練框架,含 27 個預...
    哪些支持PyTorch-Transformers(此前叫做pytorch-pretrained-bert)是面向自然語言處理,當前性能最高的預訓練模型開源庫。27個預訓練模型項目中提供了27個預訓練模型,下面是這些模型的完整列表,以及每個模型的簡短介紹。