PyTorch演算法加速指南

視學演算法發表於2020-04-06

PyTorch演算法加速指南

 點選上方“藍字”關注“視學演算法”

PyTorch演算法加速指南

原標題 | Speed Up your Algorithms Part 1 — PyTorch

作 者 | Puneet Grover

翻 譯 | 天字一號

審 校 | 鳶尾、唐裡

注:敬請點選文末【閱讀原文】訪問文中相關連結,PC檢視體驗更佳。

這是我正在撰寫的系列文章中的第一篇。所有帖子都在這裡:

1.加快演算法速度,第1部分—PyTorch

2.加快演算法速度,第2部分-Numba

3.加快演算法速度,第3部分—並行化

4.加快演算法速度,第4部分--Dask

這些與Jupyter Notebooks配套,可在此處獲得:[Github-SpeedUpYourAlgorithms]和[Kaggle]

(編輯-28/11/18)-新增了“torch.multiprocessing”部分。

目錄

  1. 介紹

  2. 如何檢查CUDA的可用性?

  3. 如何獲取有關cuda裝置的更多資訊?

  4. 如何儲存張量並在GPU上執行模型?

  5. 如果有多個GPU,如何選擇和使用GPU?

  6. 資料並行

  7. 資料並行性比較

  8. torch.multiprocessing

  9. 參考文獻

PyTorch演算法加速指南


1. 引言:

在本文中,我將展示如何使用torch和pycuda檢查、初始化GPU裝置,以及如何使演算法更快。

PyTorch是建立在torch之上的機器學習庫。它得到了Facebook AI研究小組的支援。在最近開發之後,由於它的簡單性,動態圖以及本質上是pythonic,它已經獲得了很大的普及。它的速度仍然不會落後,在許多情況下甚至可以超越其表現。

pycuda允許您從python訪問Nvidia的CUDA平行計算API。

2.如何檢查CUDA的可用性

PyTorch演算法加速指南

Sydney Rae在《 Unsplash》上創作的“沙灘上的棕色幹樹葉”

要檢查Torch是否可以使用cuda裝置,您可以簡單地執行:

import torch
torch.cuda.is_available()# True

3. 如何獲得cuda裝置更多資訊

PyTorch演算法加速指南

  Rawpixel在Unsplash上釋出的“黑色智慧手機”

要獲取裝置的基本資訊,可以使用torch.cuda。但是,要獲取有關裝置的更多資訊,可以使用pycuda,這是CUDA庫周圍的python包裝器。您可以使用類似:

import torchimport pycuda.driver as cudacuda.init()
## Get Id of default devicetorch.cuda.current_device()# 0
cuda.Device(0).name() # '0' is the id of your GPU# Tesla K80

或者

torch.cuda.get_device_name(0) # Get name device with ID '0'# 'Tesla K80'

我編寫了一個簡單的類來獲取有關您的cuda相容GPU的資訊:

PyTorch演算法加速指南

PyTorch演算法加速指南

要獲取當前的記憶體使用情況,可以使用pyTorch的函式,例如:

mport torch# Returns the current GPU memory usage by # tensors in bytes for a given devicetorch.cuda.memory_allocated()# Returns the current GPU memory managed by the# caching allocator in bytes for a given devicetorch.cuda.memory_cached()

執行應用程式後,可以使用簡單的命令清除快取:

# Releases all unoccupied cached memory currently held by# the caching allocator so that those can be used in other# GPU application and visible in nvidia-smitorch.cuda.empty_cache()

但是,使用此命令不會通過張量釋放佔用的GPU記憶體,因此它無法增加可用於PyTorch的GPU記憶體量。

這些記憶體方法僅適用於GPU。 

4. 如何在GPU上儲存張量並且執行模型?

使用 .cuda

PyTorch演算法加速指南

五隻鴿子在欄杆上棲息,一隻鴿子在飛行中---來自Nathan Dumlao  Unsplash上的作品

如果要在cpu上儲存內容,可以簡單地寫:

a = torch.DoubleTensor([1., 2.])

此向量儲存在cpu上,您對其執行的任何操作都將在cpu上完成。要將其傳輸到gpu,您只需執行.cuda:

a = torch.FloatTensor([1., 2.]).cuda()

或者

這將為其選擇預設裝置,該預設裝置可通過命令檢視

torch.cuda.current_device()# 0

也可以這樣:

a.get_device()# 0

您也可以將模型傳送到GPU裝置。例如,考慮一個由nn.Sequential組成的簡單模組:

sq = nn.Sequential(         nn.Linear(20, 20),         nn.ReLU(),         nn.Linear(20, 4),         nn.Softmax())

要將其傳送到GPU裝置,只需執行以下操作:

model = sq.cuda()

您可以檢查它是否在GPU裝置上,為此,您必須檢查其引數是否在GPU裝置上,例如:

# From the discussions here: discuss.pytorch.org/t/how-to-check-if-model-is-on-cuda
next(model.parameters()).is_cuda# True


5. 在多個GPU中,如何選擇GPU進行運算?

PyTorch演算法加速指南

NeONBRAND 在Unsplash上的“工具的選擇性聚焦攝影”

您可以為當前應用程式/儲存選擇一個GPU,該GPU可以與您為上一個應用程式/儲存選擇的GPU不同。

正如在第(2)部分中已經看到的那樣,我們可以使用pycuda獲取所有與cuda相容的裝置及其ID,在此不再贅述。

考慮到您有3個cuda相容裝置,可以將張量初始化並分配給特定裝置,如下所示:

PyTorch演算法加速指南

在這些Tensor上執行任何操作時,無論選擇哪個裝置,都可以執行該操作,結果將與Tensor儲存在同一裝置上。

x = torch.Tensor([1., 2.]).to(cuda2)y = torch.Tensor([3., 4.]).to(cuda2)
# This Tensor will be saved on 'cuda2' onlyz = x + y

如果您有多個GPU,則可將應用程式在多個裝置上工作,但是它們之間會產生通訊開銷。但是,如果您不需要太多中繼資訊,則可以嘗試一下。

其實還有一個問題。在PyTorch中,預設情況下,所有GPU操作都是非同步的。儘管在CPU和GPU或兩個GPU之間複製資料時確實進行了必要的同步,但是如果您仍然使用torch.cuda.Stream()命令建立自己的流,那麼您將必須自己照顧指令的同步 。

從PyTorch的文件中舉一個例子,這是不正確的:

cuda = torch.device('cuda')s = torch.cuda.Stream()  # Create a new stream.A = torch.empty((100, 100), device=cuda).normal_(0.0, 1.0)with torch.cuda.stream(s):    # because sum() may start execution before normal_() finishes!    B = torch.sum(A)

如果您想充分利用多個GPU,可以:

1.將所有GPU用於不同的任務/應用程式,

2.將每個GPU用於集合或堆疊中的一個模型,每個GPU都有資料副本(如果可能),因為大多數處理是在訓練模型期間完成的,

3.在每個GPU中使用帶有切片輸入和模型副本。每個GPU都會分別計算結果,並將其結果傳送到目標GPU,然後再進行進一步的計算等。

6. 資料並行?

PyTorch演算法加速指南

阿比蓋爾·基南(Abigail Keenan)在《 Unsplash》上的“森林中的樹木攝影”

在資料並行中,我們將從資料生成器獲得的資料(一個批次)分割為較小的小型批次,然後將其傳送到多個GPU進行平行計算。

在PyTorch中,資料並行是使用torch.nn.DataParallel實現的。

我們將看到一個簡單的示例來了解實際情況。為此,我們必須使用nn.parallel的一些功能,即:

1.複製:在多個裝置上覆制模組。

2.分散:在這些裝置中的第一維上分配輸入。

3.收集:從這些裝置收集和連線第一維的輸入。

4.parallel_apply:要將從Scatter獲得的一組分散式輸入s,應用於從Replicate獲得的相應分散式Module集合。

# Replicate module to devices in device_idsreplicas = nn.parallel.replicate(module, device_ids)
# Distribute input to devices in device_idsinputs = nn.parallel.scatter(input, device_ids)
# Apply the models to corresponding inputsoutputs = nn.parallel.parallel_apply(replicas, inputs)
# Gather result from all devices to output_deviceresult = nn.parallel.gather(outputs, output_device)

或者,更簡單

model = nn.DataParallel(model, device_ids=device_ids)result = model(input)

7.資料並行的比較

PyTorch演算法加速指南

Icon8團隊在Unsplash上釋出“銀鈴鬧鐘”

我沒有多個GPU,但是我可以在這裡找到Ilia Karmanov和他的github儲存庫上一篇不錯的文章,其中比較了使用多個GPU的大多數框架。

他的結果:

PyTorch演算法加速指南 

[他的github儲存庫最新更新:(2018年6月19日)]。PyTorch 1.0,Tensorflow 2.0的釋出以及新的GPU可能已經改變了這一點……]

因此,您可以看到,即使必須在開始和結束時與主裝置進行通訊,並行處理也絕對有幫助。在多GPU情況下,PyTorch的結果要比Chainer及其他所有結果都快。通過一次呼叫DataParallel,Pytorch也使其變得簡單。

8. torch.multiprocessing

PyTorch演算法加速指南

Unsplash 上Matthew Hicks作品

torch.multiprocessing是Python多處理模組的包,其API與原始模組100%相容。因此,您可以在此處使用Python的多處理模組中的Queue,Pipe,Array等。此外,為了使其更快,他們新增了一個方法share_memory_(),該方法使資料進入任何程式時都可以直接使用,因此將資料作為引數傳遞給不同的程式將不會複製該資料。

您可以共享張量,模型引數,也可以根據需要在CPU或GPU上共享它們。

PyTorch演算法加速指南

您可以在此處的“池和程式”部分中使用上面的方法,並且要獲得更快的速度,可以使用share_memory_()方法在所有程式之間共享張量,而無需複製資料。

您也可以使用機器叢集。有關更多資訊,請參見此處。

9. 參考:

  1. https://documen.tician.de/pycuda/

  2. https://pytorch.org/docs/stable/notes/cuda.html

  3. https://discuss.pytorch.org/t/how-to-check-if-model-is-on-cuda

  4. https://medium.com/@iliakarmanov/multi-gpu-rosetta-stone-d4fa96162986

感謝您的閱讀!

via https://towardsdatascience.com/speed-up-your-algorithms-part-1-pytorch-56d8a4ae7051

PyTorch演算法加速指南 點選 閱讀原文,檢視本文更多內容

- END -

如果看到這裡,說明你喜歡這篇文章,請轉發、點贊掃描下方二維碼或者微信搜尋「perfect_iscas」,新增好友後即可獲得10套程式設計師全棧課程+1000套PPT和簡歷模板向我私聊「進群」二字即可進入高質量交流群。

掃描二維碼進群↓

PyTorch演算法加速指南

PyTorch演算法加速指南

PyTorch演算法加速指南

在看 PyTorch演算法加速指南

相關文章