- PyTorch 數(shù)據(jù)并行處理
可選擇:數(shù)據(jù)并行處理(文末有完整代碼下載) 作者:Sung Kim 和 Jenny Kang
在這個教程中,我們將學(xué)習(xí)如何用 DataParallel 來使用多 GPU。 通過 PyTorch 使用多個 GPU 非常簡單玻靡。你可以將模型放在一個 GPU:
device = torch.device("cuda:0")
model.to(device)
然后蛆封,你可以復(fù)制所有的張量到 GPU:
mytensor = my_tensor.to(device)
請注意层玲,只是調(diào)用 my_tensor.to(device) 返回一個 my_tensor 新的復(fù)制在GPU上杖们,而不是重寫 my_tensor夷狰。你需要分配給他一個新的張量并且在 GPU 上使用這個張量宰闰。
在多 GPU 中執(zhí)行前饋茬贵,后饋操作是非常自然的。盡管如此移袍,PyTorch 默認(rèn)只會使用一個 GPU解藻。通過使用 DataParallel 讓你的模型并行運行,你可以很容易的在多 GPU 上運行你的操作葡盗。
model = nn.DataParallel(model)
這是整個教程的核心螟左,我們接下來將會詳細講解啡浊。 引用和參數(shù)
引入 PyTorch 模塊和定義參數(shù)
import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader
參數(shù)
input_size = 5
output_size = 2
batch_size = 30
data_size = 100
設(shè)備
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
實驗(玩具)數(shù)據(jù)
生成一個玩具數(shù)據(jù)。你只需要實現(xiàn) getitem.
class RandomDataset(Dataset):
def __init__(self, size, length):
self.len = length
self.data = torch.randn(length, size)
def __getitem__(self, index):
return self.data[index]
def __len__(self):
return self.len
rand_loader = DataLoader(dataset=RandomDataset(input_size, data_size),batch_size=batch_size, shuffle=True)
簡單模型
為了做一個小 demo胶背,我們的模型只是獲得一個輸入巷嚣,執(zhí)行一個線性操作,然后給一個輸出钳吟。盡管如此廷粒,你可以使用 DataParallel 在任何模型(CNN, RNN, Capsule Net 等等.)
我們放置了一個輸出聲明在模型中來檢測輸出和輸入張量的大小。請注意在 batch rank 0 中的輸出红且。
class Model(nn.Module):
# Our model
def __init__(self, input_size, output_size):
super(Model, self).__init__()
self.fc = nn.Linear(input_size, output_size)
def forward(self, input):
output = self.fc(input)
print("\tIn Model: input size", input.size(),
"output size", output.size())
return output
創(chuàng)建模型并且數(shù)據(jù)并行處理
這是整個教程的核心坝茎。首先我們需要一個模型的實例,然后驗證我們是否有多個 GPU暇番。如果我們有多個 GPU嗤放,我們可以用 nn.DataParallel 來 包裹 我們的模型。然后我們使用 model.to(device) 把模型放到多 GPU 中壁酬。
model = Model(input_size, output_size)
if torch.cuda.device_count() > 1:
print("Let's use", torch.cuda.device_count(), "GPUs!")
# dim = 0 [30, xxx] -> [10, ...], [10, ...], [10, ...] on 3 GPUs
model = nn.DataParallel(model)
model.to(device)
輸出:
Let's use 2 GPUs!
運行模型: 現(xiàn)在我們可以看到輸入和輸出張量的大小了次酌。
for data in rand_loader:
input = data.to(device)
output = model(input)
print("Outside: input size", input.size(),
"output_size", output.size())
輸出:
<pre style="box-sizing: border-box; font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", Courier, monospace; font-size: 1em; white-space: pre;">In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])
In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])
Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])
In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])
Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])
In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])
Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
In Model: input size torch.Size([5, 5]) output size torch.Size([5, 2])
In Model: input size torch.Size([5, 5]) output size torch.Size([5, 2])
Outside: input size torch.Size([10, 5]) output_size torch.Size([10, 2])</pre>
結(jié)果:
如果你沒有 GPU 或者只有一個 GPU,當(dāng)我們獲取 30 個輸入和 30 個輸出舆乔,模型將期望獲得 30 個輸入和 30 個輸出和措。但是如果你有多個 GPU ,你會獲得這樣的結(jié)果蜕煌。
多 GPU
如果你有 2 個GPU派阱,你會看到:
<pre style="box-sizing: border-box; font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", Courier, monospace; font-size: 1em; white-space: pre;"># on 2 GPUs
Let's use 2 GPUs!
In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])
In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])
Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])
In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])
Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])
In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])
Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
In Model: input size torch.Size([5, 5]) output size torch.Size([5, 2])
In Model: input size torch.Size([5, 5]) output size torch.Size([5, 2])
Outside: input size torch.Size([10, 5]) output_size torch.Size([10, 2])</pre>
如果你有 3個GPU,你會看到:
<pre style="box-sizing: border-box; font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", Courier, monospace; font-size: 1em; white-space: pre;">Let's use 3 GPUs!
In Model: input size torch.Size([10, 5]) output size torch.Size([10, 2])
In Model: input size torch.Size([10, 5]) output size torch.Size([10, 2])
In Model: input size torch.Size([10, 5]) output size torch.Size([10, 2])
Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
In Model: input size torch.Size([10, 5]) output size torch.Size([10, 2])
In Model: input size torch.Size([10, 5]) output size torch.Size([10, 2])
In Model: input size torch.Size([10, 5]) output size torch.Size([10, 2])
Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
In Model: input size torch.Size([10, 5]) output size torch.Size([10, 2])
In Model: input size torch.Size([10, 5]) output size torch.Size([10, 2])
In Model: input size torch.Size([10, 5]) output size torch.Size([10, 2])
Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([2, 5]) output size torch.Size([2, 2])
Outside: input size torch.Size([10, 5]) output_size torch.Size([10, 2])</pre>
如果你有 8個GPU斜纪,你會看到:
<pre style="box-sizing: border-box; font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", Courier, monospace; font-size: 1em; white-space: pre;">Let's use 8 GPUs!
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([2, 5]) output size torch.Size([2, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([2, 5]) output size torch.Size([2, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([4, 5]) output size torch.Size([4, 2])
In Model: input size torch.Size([2, 5]) output size torch.Size([2, 2])
Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])
In Model: input size torch.Size([2, 5]) output size torch.Size([2, 2])
In Model: input size torch.Size([2, 5]) output size torch.Size([2, 2])
In Model: input size torch.Size([2, 5]) output size torch.Size([2, 2])
In Model: input size torch.Size([2, 5]) output size torch.Size([2, 2])
In Model: input size torch.Size([2, 5]) output size torch.Size([2, 2])
Outside: input size torch.Size([10, 5]) output_size torch.Size([10, 2])</pre>
總結(jié)
數(shù)據(jù)并行自動拆分了你的數(shù)據(jù)并且將任務(wù)單發(fā)送到多個 GPU 上贫母。當(dāng)每一個模型都完成自己的任務(wù)之后,DataParallel 收集并且合并這些結(jié)果盒刚,然后再返回給你腺劣。
更多信息,請訪問: https://pytorch.org/tutorials/beginner/former_torchies/parallelism_tutorial.html
下載 Python 版本完整代碼:
下載 jupyter notebook 版本完整代碼: