加快Python算法的四個方法(一)PyTorch

2021-01-11 CDA數據分析師

CDA數據分析師 出品

相信大家在做一些算法經常會被龐大的數據量所造成的超多計算量需要的時間而折磨的痛苦不已,接下來我們圍繞四個方法來幫助大家加快一下Python的計算時間,減少大家在算法上的等待時間。下面為大家講述有關PyTorch的內容。

1.介紹

在PyTorch模塊中,我將展示如何使用torch和檢查、初始化GPU設備pycuda,以及如何使算法更快。

PyTorch是建立在torch的機器學習庫。它得到了Facebook AI研究小組的支持。在最近開發之後,由於它的簡單性,動態圖形以及它本質上是Python,它在被開發出來之後變得非常流行。它的速度仍然沒有落後,在很多情況下可以說是表現的非常好的。

pycuda允許你從python訪問Nvidia的CUDA並行計算API。

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

要檢查是否有cuda可用的設備Torch,可以簡單地運行一下下面的代碼:

import torchtorch.cuda.is_available()# True

3.如何獲取有關你的cuda設備的更多信息?

要獲取設備的基本信息,可以使用torch.cuda。但是,要獲取有關設備的更多信息,可以使用pycuda,這是一個圍繞CUDA庫開發的python包裝器。你可以使用:

import torchimport pycuda.driver as cudacuda.init()##獲取默認設備的Idtorch.cuda.current_device()# 0cuda.Device(0).name() # '0'是你的GPU的id# Tesla K80

或者你可以這麼用:

torch.cuda.get_device_name(0)#獲取ID為'0'的名稱設備#'Tesla K80'

我編寫了一個簡單的類來獲取有關cuda兼容GPU的信息:

#一個簡單的類來了解你的cuda設備import pycuda.driver as cudaimport pycuda.autoinit #必須使用它的功能cuda.init() # 需要使用它的功能class aboutCudaDevices():def __init__(self):passdef num_devices(self):"""返回連接的設備數量."""return cuda.Device.count()def devices(self):"""獲取所有連接設備的信息."""num = cuda.Device.count()print("%d device(s) found:"%num)for i in range(num):print(cuda.Device(i).name(), "(Id: %d)"%i)def mem_info(self):"""獲得所有設備的可用內存和總內存."""available, total = cuda.mem_get_info()print("Available: %.2f GB\nTotal: %.2f GB"%(available/1e9, total/1e9))def attributes(self, device_id=0):"""獲取設備Id的屬性 = device_id"""return cuda.Device(device_id).get_attributes()def __repr__(self):"""類表示為連接到它們的設備的數量."""num = cuda.Device.count()string = ""string += ("%d device(s) found:\n"%num)for i in range(num):string += ( " %d) %s (Id: %d)\n"%((i+1),cuda.Device(i).name(),i))string += (" Memory: %.2f GB\n"%(cuda.Device(i).total_memory()/1e9))return string# 你可以通過輸入它的名字來列印輸出(__repr__):aboutCudaDevices()# 1 設備(年代):# 1) Tesla K80 (Id: 0)# Memory: 12.00 GB

要獲取當前的內存使用情況,你可以使用pyTorch的函數:

import torch#返回當前的GPU內存使用# 一個給定設備的容量(以字節為單位)torch.cuda.memory_allocated()#函數管理的當前的GPU內存#以字節為給定設備緩存的分配器torch.cuda.memory_cached()

在運行應用程式後,可以使用一個簡單的命令來清除緩存:

# 釋放緩存分配器當前持有的所有為佔用的緩存內存# 以便這些內存可以在其他GPU應用程式中可以使用# 並且可以在NVIDIA-SMI中可以進行查看torch.cuda.empty_cache()

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

這些內存方法僅適用於GPU。所以這才是真正需要它的地方。

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

使用.cuda函數。

如果你想要在CPU上存儲一些內容,可以簡單地編寫代碼:

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

這個向量是存儲在CPU上的,你對它執行的任何操作都是在CPU上執行完成的。而要將其轉移到GPU上,你只需要執行以下操作.cuda:

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

或者,

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

這將為它選擇默認設備,該默認設備可通過以下命令查看:

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設備上,例如:

#可以在這裡進行討論: ht tp://discuss.pyt orch.org/t/how-to-che ck-if-model-is-on-cudanext(model.parameters()).is_cuda# True

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

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

正如在第(2)部分中已經看到的那樣,我們可以獲得所有與cuda兼容的設備及其Id使用pycuda的情況,在此我們就不再贅述了。

考慮到你有3個cuda兼容的設備,你可以初始化和分配tensors到一個特定的設備,就像這樣。

cuda0 = torch.device('cuda:0')cuda1 = torch.device('cuda:1')cuda2 = torch.device('cuda:2')# 如果你只使用 'cuda' , 張量/型號將會被發送到默認(當前)設備。(默認值= 0)x = torch.Tensor([1., 2.], device=cuda1)# 或者x = torch.Tensor([1., 2.]).to(cuda1)# 或者x = torch.Tensor([1., 2.]).cuda(cuda1)# 筆記:# 如果你想改變默認設備,那麼請使用:torch.cuda.set_device(2) # 設備Id為'2'的地方# 如果你只想使用3個GPU中的2個,那麼你必須設置環境變量CUDA_VISIBLE_DEVICES 等於"0,2",如果你只想使用第一個和第三個GPU的話#現在如果你想要檢查有多少個GPU時,它將顯示兩個(0,1)import osos.environ["CUDA_VISIBLE_DEVICES"] = "0,2"

當你對這些Tensors 進行任何操作時,無論選擇什麼設備,都可以執行該操作,結果會和Tensor保存在同一個設備上。

x = torch.Tensor([1., 2.]).to(cuda2)y = torch.Tensor([3., 4.]).to(cuda2)# 這個Tensor(張量)只會保存在'cuda2' 中z = x + y

如果你有多個GPU,則可以在其中劃分應用程式的工作,但是他們之間的通信會帶來開銷。但是,如果你不需要過多的進行傳遞信息,那你可以嘗試一下。

實際上還有一個問題。在PyTorch中的所有GPU操作中,默認情況下都是異步的。儘管在CPU和GPU或兩個GPU之間複製數據時確實進行了必要的同步,但是,如果你在命令torch.cuda.Stream()的幫助下創建自己的數據流,那麼你講不得不處理指令的同步

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

cuda = torch.device('cuda')s = torch.cuda.Stream() # 創建一個新的數據流.A = torch.empty((100, 100), device=cuda).normal_(0.0, 1.0)with torch.cuda.stream(s):# 因為 sum() 可能會在normal_()結束之前開始執行!B = torch.sum(A)

如果你想充分利用多個GPU,那麼你可以:

將所有GPU用於不同的任務/應用程式將每個GPU用於集合或堆棧中的一個模型,每個GPU都有數據副本(如果可能的話),因為大多數處理是在擬合模型期間完成的,在每個GPU中使用帶有切片輸入的每個GPU和模型副本。每個GPU都會分別計算結果,並將其結果發送到目標GPU,然後再進行進一步的計算等。6.數據並行性

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

在PyTorch中,數據並行中是使用torch.nn.DataParallel實現的

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

Replicate(複製):Module在多個設備上複製。Scatter(分散):input將第一個維度分配到這些設備中。Gather(聚集):input收集並連接這些設備的第一個維度。parallel_apply:將我們從我們從Scatter中得到的一套分布式的input,輸入到相應的分布式Module中,我們是通過複製得到的這些模塊。#將模塊複製到設備id中的設備replicas = nn.parallel.replicate(module, device_ids)#將輸入分配到設備id中的設備inputs = nn.parallel.scatter(input, device_ids)#將模型應用於相應的輸入outputs = nn.parallel.parallel_apply(replicas, inputs)#收集所有設備的結果到output_deviceresult = nn.parallel.gather(outputs, output_device)

或者,只需要簡單地:

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

7.數據並行比較

訓練集數據+Val w/數據加載器+SSD中對真實數據的數據擴充

訓練集W/在內存中的綜合數據

現在,你可以清楚的看到,即使必須在開始和結束時與主設備進行通信,並行處理也絕對是有幫助的。並且僅在多GPU情況下,PyTorch比所有結果提供結果的時間更快僅僅略低於Chainer。Pytorch只需要通過對DataParallel的一次調用,就會使其變得簡單。

8.torch.multiprocessing

torch.multiprocessing是Python multiprocessing模塊的包裝,其API與原始模塊100%兼容。因此,你可以在此處使用Python的多處理模塊中的Queue',Pipe',Array'等。此外,為了使其更快,他們添加了一個方法,share_memory_()該方法允許數據進入一個狀態,任何進程都可以直接使用它,因此將該數據作為參數傳遞給不同的進程將不會複製該數據。

你可以共享Tensors,模型的parameters,也可以根據需要在CPU或GPU上共享它們。

來自Pytorch的警告:(關於GPU上的共享)CUDA API要求導出到其他進程的分配只要在被其他進程使用時就保持有效。你應該小心並確保你共享的CUDA Tensors在必要時不會超出範圍。這對於共享模型參數應該不是問題,但是傳遞其他類型的數據時應格外小心。請注意,此限制不適用於共享CPU內存。

你可以在此處的「池和進程」部分中使用上面的方法,並且要獲得更快的速度,可以使用share_memory_()方法Tensor在所有進程之間共享(例如)而不被複製。

#import torch.multiprocessing as mpdef train(model):for data, labels in data_loader:optimizer.zero_grad()loss_fn(model(data), labels).backward()optimizer.step() # 這一步將更新共享參數model = nn.Sequential(nn.Linear(n_in, n_h1),nn.ReLU(),nn.Linear(n_h1, n_out))model.share_memory() # 需要 'fork' 方法工作processes = []for i in range(4): # No. 的過程p = mp.Process(target=train, args=(model,))p.start()processes.append(p)for p in processes: p.join()

下一期我們繼續看加快Python計算的另一種方法——Numba。

疫情當下,昔日匆匆的步伐終於放慢了些,也是時候好好想想自己的職業計劃和人生規劃了。提前做好準備,未雨綢繆,為未來蓄能——蓄勢待發!

相關焦點

  • 加快Python算法的四個方法(二)Numba
    CDA數據分析師 出品相信大家在做一些算法經常會被龐大的數據量所造成的超多計算量需要的時間而折磨的痛苦不已,接下來我們圍繞四個方法來幫助大家加快一下Python的計算時間,減少大家在算法上的等待時間。今天給大家介紹Numba這一塊的內容。1.簡介所以什麼是Numba呢?
  • 加快Python算法的四個方法(三)數據並行化
    CDA數據分析師 出品相信大家在做一些算法經常會被龐大的數據量所造成的超多計算量需要的時間而折磨的痛苦不已,接下來我們圍繞四個方法來幫助大家加快一下Python的計算時間,減少大家在算法上的等待時間。以下給大家講解關於數據並行化這方面的內容。
  • Pytorch框架安裝方法(基於Anaconda環境和Pycharm IDE)
    1.6 單擊啟動Anaconda Prompt 創建虛擬「房間」通過conda創建一個名為:pytorch的虛擬「房間」,可以方便未來對不同版本的PyTorch進行管理,具體方法如下:conda create -n pytorch python=3.61.7 查看創建的「房間」方法:conda info --envs
  • 用正確方法對度量學習算法進行基準測試
    但最近一些論文的官方開源實現表明,他們實際上使用的是 GoogleNet 論文中描述的更複雜的裁剪方法(見「訓練方法」)。3.性能提升技巧在論文中沒有提及。在最近一篇 2019 年論文的官方開原始碼中,主幹模型的 BatchNorm 參數在訓練期間被凍結。作者解釋說,這有助於減少過度擬合,讓 CUB200 數據集的性能提高 2 個點。
  • 乾貨| 請收下這份2018學習清單:150個最好的機器學習,NLP和Python...
    一般我會找一個有意思的教程或者視頻,再由此找到三四個,甚至更多的教程或者視頻。猛回頭,發現標收藏夾又多了20個資源待我學習(推薦提升效率工具Tab Bundler)。找到超過25個有關ML的「小抄」後,我寫一篇博文(https://unsupervisedmethods.com/cheat-sheet-of-machine-learning-and-python-and-math-cheat-sheets-a4afe4e791b6),裡面的資源都有超連結。
  • ...請收下這份2018學習清單:150個最好的機器學習,NLP和Python教程
    一般我會找一個有意思的教程或者視頻,再由此找到三四個,甚至更多的教程或者視頻。猛回頭,發現標收藏夾又多了20個資源待我學習(推薦提升效率工具Tab Bundler)。找到超過25個有關ML的「小抄」後,我寫一篇博文(https://unsupervisedmethods.com/cheat-sheet-of-machine-learning-and-python-and-math-cheat-sheets-a4afe4e791b6),裡面的資源都有超連結。
  • 乾貨 | 請收下這份2018學習清單:150個最好的機器學習,NLP和Python教程
    一般我會找一個有意思的教程或者視頻,再由此找到三四個,甚至更多的教程或者視頻。猛回頭,發現標收藏夾又多了20個資源待我學習(推薦提升效率工具Tab Bundler)。 找到超過25個有關ML的「小抄」後,我寫一篇博文(https://unsupervisedmethods.com/cheat-sheet-of-machine-learning-and-python-and-math-cheat-sheets-a4afe4e791b6),裡面的資源都有超連結。
  • 算法工程師路線圖(經驗濃縮,純乾貨!)
    而網際網路公司的算法工程師崗位中這個算法則是機器學習算法,說的通俗點,就是人工智慧領域中的算法,它是關於如何讓機器自動學習和挖掘數據中的規律,並使用算法和模型對未來進行預測。目前來說這也是網際網路行業中最熱門的一個崗位,開出的薪酬也普遍高於開發崗。今天我就來分享下算法工程師的學習路徑,並推薦一些我認為特別有價值的學習資料和學習方法。
  • PyTorch框架歷史和特性更迭與安裝過程
    在安裝Anaconda以後,我們可以使用Anaconda創建一個虛擬環境,具體的命令為conda create-n pytorch python=3.7。可以看到這裡有兩個參數,第一個參數是-n,後面緊接著虛擬環境的名字,這裡直接使用pytorch作為虛擬環境的名字(讀者可以使用任意的字符作為虛擬環境的名字),另外一個參數則用於指定Python的版本(這裡使用3.7版本)。
  • 《PyTorch中文手冊》來了
    PyTorch 現在是 GitHub 上增長速度第二快的開源項目,在過去的 12 個月裡,貢獻者增加了 2.8 倍。而且,去年 12 月在 NeurIPS 大會上,PyTorch 1.0 穩定版終於發布。
  • 一文總結數據科學家常用的Python庫(下)
    嗯,這是一個基於Python的科學計算包,可以用作:NumPy的替代品,可以使用GPU的強大功能深度學習研究平臺,提供最大的靈活性和速度轉到此處(https://pytorch.org/get-started/locally/)查看不同作業系統的安裝過程。
  • Pytorch-Transformers 1.0 發布,支持六個預訓練框架,含 27 個預...
    27個預訓練模型項目中提供了27個預訓練模型,下面是這些模型的完整列表,以及每個模型的簡短介紹。作者在doc中展示了幾個基於BERT原始實現(https://github.com/google-research/bert/)和擴展的微調示例,分別為:九個不同GLUE任務的序列級分類器;問答集數據集SQUAD上的令牌級分類器;SWAG分類語料庫中的序列級多選分類器;
  • 華為雲應用編排,手把手教您完成pytorch代碼部署
    本文將以一個使用了pytorch的demo代碼pytorch-classify為例,通過華為雲上的容器服務一鍵式部署, 5 分鐘完成免費的雲上pytorch代碼的部署。傳統部署方式首先是準備環境。先有個伺服器,這臺伺服器需要能夠被外部訪問。
  • 13個算法工程師必須掌握的PyTorch Tricks
    本文轉載自【微信公眾號:機器學習算法與Python精研 ,ID:AITop100】,經微信公眾號授權轉載,如需轉載原文作者聯繫目錄1、指定GPU編號2、查看模型每層輸出詳情3、梯度裁剪4、擴展單張圖片維度5、one hot編碼6、防止驗證模型時爆顯存7、學習率衰減
  • Facebook 發布 Detectron2:基於 PyTorch 的新一代目標檢測工具
    雷鋒網 AI 開發者按:Detectron 是 FAIR 在 2018 年初公開的目標檢測平臺,包含了大量業內最具代表性的目標檢測、圖像分割、關鍵點檢測算法,該框架主要基於 python 和 caffe2 實現,開源項目已獲得了超 2.2w 的星標數。
  • 一文讀懂遺傳算法工作原理(附Python實現)
    於是,我開始研究可以提高分數的優化方法。結果我果然找到了一個,它叫遺傳算法。在把它應用到超市銷售問題之後,最終我的分數在排行榜上一下躍居前列。 因此,為了形式化定義一個遺傳算法,我們可以將它看作一個優化方法,它可以嘗試找出某些輸入,憑藉這些輸入我們便可以得到最佳的輸出值或者是結果。
  • PyTorch中使用DistributedDataParallel進行多GPU分布式模型訓練
    例如,如果這個腳本要在一個有4個gpu的強大機器上執行,WORLDSIZE應該是4(因為torch.cuda.device_count() == 4),所以是mp.spawn會產生4個不同的進程,它們的等級 分別是0、1、2或3。等級為0的進程被賦予一些額外的職責,因此被稱為主進程。當前進程的等級將作為派生入口點(在本例中為訓練方法)作為其第一個參數傳遞。
  • 13個小案例輕鬆認識python
    python流行一段時間了,開始的就感覺只是一種新的語言罷了,可是這個世界總是對新事物非常尊崇,平時用的不多,看起來也沒多大動力,結合著平時講VB(信息技術《算法與程序設計》9講)的套路,用案例簡單自學下python,這13個小案例不像網絡上的圖形處理等那麼酷炫,不能做出酷炫的作品,也沒有涉及基礎的算法,但也是python的基礎吧
  • Pytorch中的分布式神經網絡訓練|pytorch|bat|拆分|調用_網易訂閱
    · 積累梯度  · 使用nn.DataParallel  · 使用nn.DistributedDataParallel積累梯度  在GPU之間拆分批次的最簡單方法是累積梯度。 假設我們要訓練的批處理大小為256,但是一個GPU內存只能容納32個批處理大小。
  • 雲計算學習:用PyTorch實現一個簡單的分類器
    回想了一下自己關於 pytorch 的學習路線,一開始找的各種資料,寫下來都能跑,但是卻沒有給自己體會到學習的過程。有的教程一上來就是寫一個 cnn,雖然其實內容很簡單,但是直接上手容易讓人找不到重點,學的雲裡霧裡。有的教程又淺嘗輒止,師傅領到了門檻跟前,總感覺自己還沒有進門,教程就結束了。