PyTorch算法加速指南
點(diǎn)擊上方“小白學(xué)視覺”,選擇加"星標(biāo)"或“置頂”
重磅干貨,第一時間送達(dá)
本文轉(zhuǎn)自|視覺算法 這是我們正在撰寫的系列文章中的第一篇。所有帖子都在這里: 1.加快算法速度,第1部分—PyTorch
2.加快算法速度,第2部分-Numba
3.加快算法速度,第3部分—并行化
4.加快算法速度,第4部分--Dask
這些與Jupyter Notebooks配套,可在此處獲得:[Github-SpeedUpYourAlgorithms]和[Kaggle]
(編輯-28/11/18)-添加了“torch.multiprocessing”部分。
目錄
介紹
如何檢查CUDA的可用性?
如何獲取有關(guān)cuda設(shè)備的更多信息?
如何存儲張量并在GPU上運(yùn)行模型?
如果有多個GPU,如何選擇和使用GPU?
數(shù)據(jù)并行
數(shù)據(jù)并行性比較
torch.multiprocessing
參考文獻(xiàn)
1.引言 在本文中,我將展示如何使用torch和pycuda檢查、初始化GPU設(shè)備,以及如何使算法更快。
PyTorch是建立在torch之上的機(jī)器學(xué)習(xí)庫。它得到了Facebook AI研究小組的支持。在最近開發(fā)之后,由于它的簡單性,動態(tài)圖以及本質(zhì)上是pythonic,它已經(jīng)獲得了很大的普及。它的速度仍然不會落后,在許多情況下甚至可以超越其表現(xiàn)。
pycuda允許您從python訪問Nvidia的CUDA并行計(jì)算API。
2.如何檢查CUDA的可用性
Sydney Rae在《 Unsplash》上創(chuàng)作的“沙灘上的棕色干樹葉”
要檢查Torch是否可以使用cuda設(shè)備,您可以簡單地運(yùn)行:
import torchtorch.cuda.is_available()# True3.如何獲得cuda設(shè)備的更多信息
Rawpixel在Unsplash上發(fā)布的“黑色智能手機(jī)”
要獲取設(shè)備的基本信息,可以使用torch.cuda。但是,要獲取有關(guān)設(shè)備的更多信息,可以使用pycuda,這是CUDA庫周圍的python包裝器。您可以使用類似:
import torchimport pycuda.driver as cudacuda.init()## Get Id of default devicetorch.cuda.current_device()# 0cuda.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'我編寫了一個簡單的類來獲取有關(guān)您的cuda兼容GPU的信息:
要獲取當(dāng)前的內(nèi)存使用情況,可以使用pyTorch的函數(shù),例如:
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()運(yùn)行應(yīng)用程序后,可以使用簡單的命令清除緩存:
# 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內(nèi)存,因此它無法增加可用于PyTorch的GPU內(nèi)存量。
這些內(nèi)存方法僅適用于GPU。
4.如何在GPU上存儲張量并且運(yùn)行模型? 使用 .cuda
五只鴿子在欄桿上棲息,一只鴿子在飛行中---來自Nathan Dumlao Unsplash上的作品
如果要在cpu上存儲內(nèi)容,可以簡單地寫:
a = torch.DoubleTensor([1., 2.])此向量存儲在cpu上,您對其執(zhí)行的任何操作都將在cpu上完成。要將其傳輸?shù)絞pu,您只需執(zhí)行.cuda:
a = torch.FloatTensor([1., 2.]).cuda()或者
這將為其選擇默認(rèn)設(shè)備,該默認(rèn)設(shè)備可通過命令查看
torch.cuda.current_device()# 0也可以這樣:
a.get_device()# 0您也可以將模型發(fā)送到GPU設(shè)備。例如,考慮一個由nn.Sequential組成的簡單模塊:
sq = nn.Sequential(nn.Linear(20, 20),nn.ReLU(),nn.Linear(20, 4),nn.Softmax())要將其發(fā)送到GPU設(shè)備,只需執(zhí)行以下操作:
model = sq.cuda()您可以檢查它是否在GPU設(shè)備上,為此,您必須檢查其參數(shù)是否在GPU設(shè)備上,例如: # From the discussions here: discuss.pytorch.org/t/how-to-check-if-model-is-on-cudanext(model.parameters()).is_cuda# True5.在多個GPU中,如何選擇GPU進(jìn)行運(yùn)算? NeONBRAND 在Unsplash上的“工具的選擇性聚焦攝影” 您可以為當(dāng)前應(yīng)用程序/存儲選擇一個GPU,該GPU可以與您為上一個應(yīng)用程序/存儲選擇的GPU不同。 正如在第(2)部分中已經(jīng)看到的那樣,我們可以使用pycuda獲取所有與cuda兼容的設(shè)備及其ID,在此不再贅述。 考慮到您有3個cuda兼容設(shè)備,可以將張量初始化并分配給特定設(shè)備,如下所示: 在這些Tensor上執(zhí)行任何操作時,無論選擇哪個設(shè)備,都可以執(zhí)行該操作,結(jié)果將與Tensor保存在同一設(shè)備上。 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,則可將應(yīng)用程序在多個設(shè)備上工作,但是它們之間會產(chǎn)生通信開銷。但是,如果您不需要太多中繼信息,則可以嘗試一下。 其實(shí)還有一個問題。在PyTorch中,默認(rèn)情況下,所有GPU操作都是異步的。盡管在CPU和GPU或兩個GPU之間復(fù)制數(shù)據(jù)時確實(shí)進(jìn)行了必要的同步,但是如果您仍然使用torch.cuda.Stream()命令創(chuàng)建自己的流,那么您將必須自己照顧指令的同步 。 從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用于不同的任務(wù)/應(yīng)用程序, 2.將每個GPU用于集合或堆棧中的一個模型,每個GPU都有數(shù)據(jù)副本(如果可能),因?yàn)榇蠖鄶?shù)處理是在訓(xùn)練模型期間完成的, 3.在每個GPU中使用帶有切片輸入和模型副本。每個GPU都會分別計(jì)算結(jié)果,并將其結(jié)果發(fā)送到目標(biāo)GPU,然后再進(jìn)行進(jìn)一步的計(jì)算等。 6.數(shù)據(jù)并行 阿比蓋爾·基南(Abigail Keenan)在《 Unsplash》上的“森林中的樹木攝影” 在數(shù)據(jù)并行中,我們將從數(shù)據(jù)生成器獲得的數(shù)據(jù)(一個批次)分割為較小的小型批次,然后將其發(fā)送到多個GPU進(jìn)行并行計(jì)算。 在PyTorch中,數(shù)據(jù)并行是使用torch.nn.DataParallel實(shí)現(xiàn)的。 我們將看到一個簡單的示例來了解實(shí)際情況。為此,我們必須使用nn.parallel的一些功能,即: 1.復(fù)制:在多個設(shè)備上復(fù)制模塊。 2.分散:在這些設(shè)備中的第一維上分配輸入。 3.收集:從這些設(shè)備收集和連接第一維的輸入。 4.parallel_apply:要將從Scatter獲得的一組分布式輸入s,應(yīng)用于從Replicate獲得的相應(yīng)分布式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.數(shù)據(jù)并行比較 Icon8團(tuán)隊(duì)在Unsplash上發(fā)布“銀鈴鬧鐘” 我沒有多個GPU,但是我可以在這里找到Ilia Karmanov和他的github存儲庫上一篇不錯的文章,其中比較了使用多個GPU的大多數(shù)框架。 他的結(jié)果: ![]()
[他的github存儲庫最新更新:(2018年6月19日)]。PyTorch 1.0,Tensorflow 2.0的發(fā)布以及新的GPU可能已經(jīng)改變了這一點(diǎn)……] 因此,您可以看到,即使必須在開始和結(jié)束時與主設(shè)備進(jìn)行通信,并行處理也絕對有幫助。在多GPU情況下,PyTorch的結(jié)果要比Chainer及其他所有結(jié)果都快。通過一次調(diào)用DataParallel,Pytorch也使其變得簡單。 8.torch.multiprocessing Unsplash 上Matthew Hicks作品 torch.multiprocessing是Python多處理模塊的包,其API與原始模塊100%兼容。因此,您可以在此處使用Python的多處理模塊中的Queue,Pipe,Array等。此外,為了使其更快,他們添加了一個方法share_memory_(),該方法使數(shù)據(jù)進(jìn)入任何進(jìn)程時都可以直接使用,因此將數(shù)據(jù)作為參數(shù)傳遞給不同的進(jìn)程將不會復(fù)制該數(shù)據(jù)。 您可以共享張量,模型參數(shù),也可以根據(jù)需要在CPU或GPU上共享它們。 您可以在此處的“池和進(jìn)程”部分中使用上面的方法,并且要獲得更快的速度,可以使用share_memory_()方法在所有進(jìn)程之間共享張量,而無需復(fù)制數(shù)據(jù)。 您也可以使用機(jī)器集群。有關(guān)更多信息,請參見此處。 9.參考
https://documen.tician.de/pycuda/ https://pytorch.org/docs/stable/notes/cuda.html https://discuss.pytorch.org/t/how-to-check-if-model-is-on-cuda https://medium.com/@iliakarmanov/multi-gpu-rosetta-stone-d4fa96162986 感謝您的閱讀! via https://towardsdatascience.com/speed-up-your-algorithms-part-1-pytorch-56d8a4ae7051
- END -
好消息,小白學(xué)視覺團(tuán)隊(duì)的知識星球開通啦,為了感謝大家的支持與厚愛,團(tuán)隊(duì)決定將價(jià)值149元的知識星球現(xiàn)時免費(fèi)加入。各位小伙伴們要抓住機(jī)會哦!

交流群
歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器、自動駕駛、計(jì)算攝影、檢測、分割、識別、醫(yī)學(xué)影像、GAN、算法競賽等微信群(以后會逐漸細(xì)分),請掃描下面微信號加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會根據(jù)研究方向邀請進(jìn)入相關(guān)微信群。請勿在群內(nèi)發(fā)送廣告,否則會請出群,謝謝理解~














