PyTorch 60 分鐘入門教程:資料並行處理

磐創AI發表於2018-12-29

PyTorch 60 分鐘入門教程:資料並行處理

作者 | fendouai

編輯 | 安可

出品 | 磐創AI技術團隊

在這個教程中,我們將學習如何用 DataParallel 來使用多 GPU。
通過 PyTorch 使用多個 GPU 非常簡單。你可以將模型放在一個 GPU:

 device = torch.device("cuda:0")  model.to(device)

然後,你可以複製所有的張量到 GPU:

 mytensor = my_tensor.to(device)

請注意,只是呼叫 my_tensor.to(device) 返回一個 my_tensor 新的複製在GPU上,而不是重寫 my_tensor。你需要分配給他一個新的張量並且在 GPU 上使用這個張量。

在多 GPU 中執行前饋,後饋操作是非常自然的。儘管如此,PyTorch 預設只會使用一個 GPU。通過使用 DataParallel 讓你的模型並行執行,你可以很容易的在多 GPU 上執行你的操作。

 model = nn.DataParallel(model)

這是整個教程的核心,我們接下來將會詳細講解。

引用和引數

引入 PyTorch 模組和定義引數

 import torch  import torch.nn as nn  from torch.utils.data import Dataset, DataLoader

# 引數

 input_size = 5  output_size = 2   batch_size = 30  data_size = 100

裝置

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

實驗(玩具)資料

生成一個玩具資料。你只需要實現 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.lenrand_loader = DataLoader(dataset=RandomDataset(input_size, data_size),batch_size=batch_size, shuffle=True)

簡單模型

為了做一個小 demo,我們的模型只是獲得一個輸入,執行一個線性操作,然後給一個輸出。儘管如此,你可以使用 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

建立模型並且資料並行處理

這是整個教程的核心。首先我們需要一個模型的例項,然後驗證我們是否有多個 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!

執行模型:

現在我們可以看到輸入和輸出張量的大小了。

for data in rand_loader:
    input = data.to(device)
    output = model(input)
    print("Outside: input size", input.size(),
          "output_size", output.size())

輸出:

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])

結果:

如果你沒有 GPU 或者只有一個 GPU,當我們獲取 30 個輸入和 30 個輸出,模型將期望獲得 30 個輸入和 30 個輸出。但是如果你有多個 GPU ,你會獲得這樣的結果。

多 GPU

如果你有 2 個GPU,你會看到:

# on 2 GPUsLet'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])

如果你有 3個GPU,你會看到:

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])

如果你有 8個GPU,你會看到:

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])

總結

資料並行自動拆分了你的資料並且將任務單傳送到多個 GPU 上。當每一個模型都完成自己的任務之後,DataParallel 收集並且合併這些結果,然後再返回給你。

更多資訊,請訪問:
https://pytorch.org/tutorials/beginner/former_torchies/parallelism_tutorial.html

下載 Python 版本完整程式碼:data_parallel_tutorial.py

下載 jupyter notebook 版本完整程式碼:data_parallel_tutorial.ipynb


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31555081/viewspace-2286963/,如需轉載,請註明出處,否則將追究法律責任。

相關文章