電子發(fā)燒友App

硬聲App

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示
創(chuàng)作
電子發(fā)燒友網(wǎng)>電子資料下載>電子資料>PyTorch教程13.2之異步計算

PyTorch教程13.2之異步計算

2023-06-05 | pdf | 0.27 MB | 次下載 | 免費

資料介紹

當今的計算機是高度并行的系統(tǒng),由多個 CPU 內(nèi)核(通常每個內(nèi)核多個線程)、每個 GPU 多個處理元素以及每個設(shè)備通常多個 GPU 組成。簡而言之,我們可以同時處理許多不同的事情,通常是在不同的設(shè)備上。不幸的是,Python 并不是編寫并行和異步代碼的好方法,至少在沒有一些額外幫助的情況下是這樣。畢竟 Python 是單線程的,這在未來不太可能改變。MXNet 和 TensorFlow深度學(xué)習(xí)框架采用 異步編程模型來提高性能,而 PyTorch 使用 Python 自己的調(diào)度程序?qū)е虏煌男阅軝?quán)衡。對于 PyTorch,默認情況下,GPU 操作是異步的。當您調(diào)用使用 GPU 的函數(shù)時,操作會排入特定設(shè)備的隊列,但不一定會在稍后執(zhí)行。這使我們能夠并行執(zhí)行更多計算,包括在 CPU 或其他 GPU 上的操作。

因此,了解異步編程的工作原理有助于我們通過主動減少計算要求和相互依賴性來開發(fā)更高效的程序。這使我們能夠減少內(nèi)存開銷并提高處理器利用率。

import os
import subprocess
import numpy
import torch
from torch import nn
from d2l import torch as d2l
import os
import subprocess
import numpy
from mxnet import autograd, gluon, np, npx
from mxnet.gluon import nn
from d2l import mxnet as d2l

npx.set_np()

13.2.1。通過后端異步

作為熱身,請考慮以下玩具問題:我們想要生成一個隨機矩陣并將其相乘。讓我們在 NumPy 和 PyTorch 張量中都這樣做以查看差異。請注意,PyTorchtensor是在 GPU 上定義的。

# Warmup for GPU computation
device = d2l.try_gpu()
a = torch.randn(size=(1000, 1000), device=device)
b = torch.mm(a, a)

with d2l.Benchmark('numpy'):
  for _ in range(10):
    a = numpy.random.normal(size=(1000, 1000))
    b = numpy.dot(a, a)

with d2l.Benchmark('torch'):
  for _ in range(10):
    a = torch.randn(size=(1000, 1000), device=device)
    b = torch.mm(a, a)
numpy: 2.2001 sec
torch: 0.0057 sec

通過 PyTorch 的基準輸出要快幾個數(shù)量級。NumPy 點積在 CPU 處理器上執(zhí)行,而 PyTorch 矩陣乘法在 GPU 上執(zhí)行,因此后者預(yù)計會更快。但巨大的時差表明一定有其他事情在發(fā)生。默認情況下,GPU 操作在 PyTorch 中是異步的。強制 PyTorch 在返回之前完成所有計算顯示了之前發(fā)生的情況:計算由后端執(zhí)行,而前端將控制權(quán)返回給 Python。

with d2l.Benchmark():
  for _ in range(10):
    a = torch.randn(size=(1000, 1000), device=device)
    b = torch.mm(a, a)
  torch.cuda.synchronize(device)
Done: 0.0039 sec

從廣義上講,PyTorch 有一個用于與用戶直接交互的前端(例如,通過 Python),以及一個供系統(tǒng)用來執(zhí)行計算的后端。如圖13.2.1所示,用戶可以使用Python、C++等多種前端語言編寫PyTorch程序。無論使用何種前端編程語言,PyTorch 程序的執(zhí)行主要發(fā)生在 C++ 實現(xiàn)的后端。前端語言發(fā)出的操作被傳遞到后端執(zhí)行。后端管理自己的線程,這些線程不斷收集和執(zhí)行排隊的任務(wù)。請注意,要使其正常工作,后端必須能夠跟蹤計算圖中各個步驟之間的依賴關(guān)系。因此,不可能并行化相互依賴的操作。

For a warmup consider the following toy problem: we want to generate a random matrix and multiply it. Let’s do that both in NumPy and in mxnet.np to see the difference.

with d2l.Benchmark('numpy'):
  for _ in range(10):
    a = numpy.random.normal(size=(1000, 1000))
    b = numpy.dot(a, a)

with d2l.Benchmark('mxnet.np'):
  for _ in range(10):
    a = np.random.normal(size=(1000, 1000))
    b = np.dot(a, a)
numpy: 2.1419 sec
mxnet.np: 0.0728 sec

The benchmark output via MXNet is orders of magnitude faster. Since both are executed on the same processor something else must be going on. Forcing MXNet to finish all the backend computation prior to returning shows what happened previously: computation is executed by the backend while the frontend returns control to Python.

with d2l.Benchmark():
  for _ in range(10):
    a = np.random.normal(size=(1000, 1000))
    b = np.dot(a, a)
  npx.waitall()
Done: 2.1325 sec

Broadly speaking, MXNet has a frontend for direct interactions with users, e.g., via Python, as well as a backend used by the system to perform the computation. As shown in Fig. 13.2.1, users can write MXNet programs in various frontend languages, such as Python, R, Scala, and C++. Regardless of the frontend programming language used, the execution of MXNet programs occurs primarily in the backend of C++ implementations. Operations issued by the frontend language are passed on to the backend for execution. The backend manages its own threads that continuously collect and execute queued tasks. Note that for this to work the backend must be able to keep track of the dependencies between various steps in the computational graph. Hence, it is not possible to parallelize operations that depend on each other.

https://file.elecfans.com/web2/M00/A9/38/pYYBAGR3JV2AP9YmAAMyVzf4gz4123.png

圖 13.2.1編程語言前端和深度學(xué)習(xí)框架后端。

讓我們看另一個玩具示例以更好地理解依賴關(guān)系圖。

x = torch.ones((1, 2), device=device)
y = torch.ones((1, 2), device=device)
z = x * y + 2
z
tensor([[3., 3.]], device='cuda:0')
x = np.ones((1, 2))
y = np.ones((1, 2))
z = x * y + 2
z
array([[3., 3.]])
https://file.elecfans.com/web2/M00/AA/46/pYYBAGR9OpWAYqN7AABuMUC0sRc200.svg

圖 13.2.2后端跟蹤計算圖中各個步驟之間的依賴關(guān)系。

上面的代碼片段也如圖 13.2.2所示 每當 Python 前端線程執(zhí)行前三個語句之一時,它只是將任務(wù)返回到后端隊列。當需要打印最后一條語句的結(jié)果時, Python 前端線程將等待 C++ 后端線程完成對變量結(jié)果的計算z。這種設(shè)計的一個好處是 Python 前端線程不需要執(zhí)行實際計算。因此,無論 Python 的性能如何,對程序的整體性能影響都很小。 圖 13.2.3說明了前端和后端如何交互。

https://file.elecfans.com/web2/M00/AA/46/pYYBAGR9OpeAW4-ZAAF-uY5QXNk814.svg

圖 13.2.3前后端交互。

13.2.2。障礙和阻滯劑

有許多操作會強制 Python 等待完成:

  • 最明顯的npx.waitall()是等待所有計算完成,而不管計算指令何時發(fā)出。在實踐中,除非絕對必要,否則使用此運算符不是一個好主意,因為它會導(dǎo)致性能不佳。

  • 如果我們只想等到特定變量可用,我們可以調(diào)用z.wait_to_read(). z在這種情況下,MXNet 會阻止返回 Python,直到計算出變量為止。之后可能會繼續(xù)進行其他計算。

讓我們看看這在實踐中是如何工作的。

with d2l.Benchmark('waitall'):
  b = np.dot(a, a)
  npx.waitall()

with d2l.Benchmark('wait_to_read'):
  b = np.dot(a, a)
  b.wait_to_read()
waitall: 0.0155 sec
wait_to_read: 0.0500 sec

完成這兩個操作大約需要相同的時間。除了明顯的阻塞操作之外,我們建議您了解 隱式阻塞程序。打印變量顯然需要變量可用,因此是一個障礙。最后,轉(zhuǎn)換為 NumPy via z.asnumpy()和轉(zhuǎn)換為標量 viaz.item()是阻塞的,因為 NumPy 沒有異步的概念。它需要像函數(shù)一樣訪問值print。

頻繁地將少量數(shù)據(jù)從 MXNet 的范圍復(fù)制到 NumPy 并返回可能會破壞原本高效代碼的性能,因為每個此類操作都需要計算圖來評估獲得相關(guān)術(shù)語所需的所有中間結(jié)果,然后才能完成任何其他操作。

with d2l.Benchmark('numpy conversion'):
  b = np.dot(a, a)
  b.asnumpy()

with d2l.Benchmark('scalar conversion'):
  b = np.dot(a, a)
  b.sum().item()
numpy conversion: 0.0780 sec
scalar conversion: 0.0727 sec

13.2.3。改進計算

在高度多線程的系統(tǒng)上(即使是普通筆記本電腦也有 4 個或更多線程,而在多插槽服務(wù)器上,這個數(shù)字可能超過 256),調(diào)度操作的開銷會變得很大。這就是為什么非常需要異步和并行進行計算和調(diào)度的原因。為了說明這樣做的好處,讓我們看看如果我們將變量遞增 1 多次(順序或異步)會發(fā)生什么。我們通過wait_to_read在每次添加之間插入一個屏障來模擬同步執(zhí)行。

with d2l.Benchmark('synchronous'):
  for _ in range(10000):
    y = x + 1
    y.wait_to_read()

with d2l.Benchmark('asynchronous'):
  for _ in range(10000):
    y = x + 1
  npx.waitall()
synchronous: 1.4076 sec
asynchronous: 1.1700 sec

Python前端線程和C++后端線程之間的一個稍微簡化的交互可以概括如下: 1. 前端命令后端將計算任務(wù)插入到隊列中。1. 后端從隊列中接收計算任務(wù)并進行實際計算。1. 后端將計算結(jié)果返回給前端。假設(shè)這三個階段的持續(xù)時間是y = x + 1t1,t2t3, 分別。如果我們不使用異步編程,執(zhí)行 10000 次計算所花費的總時間大約是10000(t1+t2+t3)


評論

查看更多

下載排行

本周

  1. 1山景DSP芯片AP8248A2數(shù)據(jù)手冊
  2. 1.06 MB  |  532次下載  |  免費
  3. 2RK3399完整板原理圖(支持平板,盒子VR)
  4. 3.28 MB  |  339次下載  |  免費
  5. 3TC358743XBG評估板參考手冊
  6. 1.36 MB  |  330次下載  |  免費
  7. 4DFM軟件使用教程
  8. 0.84 MB  |  295次下載  |  免費
  9. 5元宇宙深度解析—未來的未來-風口還是泡沫
  10. 6.40 MB  |  227次下載  |  免費
  11. 6迪文DGUS開發(fā)指南
  12. 31.67 MB  |  194次下載  |  免費
  13. 7元宇宙底層硬件系列報告
  14. 13.42 MB  |  182次下載  |  免費
  15. 8FP5207XR-G1中文應(yīng)用手冊
  16. 1.09 MB  |  178次下載  |  免費

本月

  1. 1OrCAD10.5下載OrCAD10.5中文版軟件
  2. 0.00 MB  |  234315次下載  |  免費
  3. 2555集成電路應(yīng)用800例(新編版)
  4. 0.00 MB  |  33566次下載  |  免費
  5. 3接口電路圖大全
  6. 未知  |  30323次下載  |  免費
  7. 4開關(guān)電源設(shè)計實例指南
  8. 未知  |  21549次下載  |  免費
  9. 5電氣工程師手冊免費下載(新編第二版pdf電子書)
  10. 0.00 MB  |  15349次下載  |  免費
  11. 6數(shù)字電路基礎(chǔ)pdf(下載)
  12. 未知  |  13750次下載  |  免費
  13. 7電子制作實例集錦 下載
  14. 未知  |  8113次下載  |  免費
  15. 8《LED驅(qū)動電路設(shè)計》 溫德爾著
  16. 0.00 MB  |  6656次下載  |  免費

總榜

  1. 1matlab軟件下載入口
  2. 未知  |  935054次下載  |  免費
  3. 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
  4. 78.1 MB  |  537798次下載  |  免費
  5. 3MATLAB 7.1 下載 (含軟件介紹)
  6. 未知  |  420027次下載  |  免費
  7. 4OrCAD10.5下載OrCAD10.5中文版軟件
  8. 0.00 MB  |  234315次下載  |  免費
  9. 5Altium DXP2002下載入口
  10. 未知  |  233046次下載  |  免費
  11. 6電路仿真軟件multisim 10.0免費下載
  12. 340992  |  191187次下載  |  免費
  13. 7十天學(xué)會AVR單片機與C語言視頻教程 下載
  14. 158M  |  183279次下載  |  免費
  15. 8proe5.0野火版下載(中文版免費下載)
  16. 未知  |  138040次下載  |  免費