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

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

3天內(nèi)不再提示

PyTorch教程-13.2. 異步計(jì)算

jf_pJlTbmA9 ? 來(lái)源:PyTorch ? 作者:PyTorch ? 2023-06-05 15:44 ? 次閱讀

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

因此,了解異步編程的工作原理有助于我們通過(guò)主動(dòng)減少計(jì)算要求和相互依賴性來(lái)開發(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。通過(guò)后端異步

作為熱身,請(qǐng)考慮以下玩具問(wèn)題:我們想要生成一個(gè)隨機(jī)矩陣并將其相乘。讓我們?cè)?NumPy 和 PyTorch 張量中都這樣做以查看差異。請(qǐng)注意,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

通過(guò) PyTorch 的基準(zhǔn)輸出要快幾個(gè)數(shù)量級(jí)。NumPy 點(diǎn)積在 CPU 處理器上執(zhí)行,而 PyTorch 矩陣乘法在 GPU 上執(zhí)行,因此后者預(yù)計(jì)會(huì)更快。但巨大的時(shí)差表明一定有其他事情在發(fā)生。默認(rèn)情況下,GPU 操作在 PyTorch 中是異步的。強(qiáng)制 PyTorch 在返回之前完成所有計(jì)算顯示了之前發(fā)生的情況:計(jì)算由后端執(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 有一個(gè)用于與用戶直接交互的前端(例如,通過(guò) Python),以及一個(gè)供系統(tǒng)用來(lái)執(zhí)行計(jì)算的后端。如圖13.2.1所示,用戶可以使用Python、C++等多種前端語(yǔ)言編寫PyTorch程序。無(wú)論使用何種前端編程語(yǔ)言,PyTorch 程序的執(zhí)行主要發(fā)生在 C++ 實(shí)現(xiàn)的后端。前端語(yǔ)言發(fā)出的操作被傳遞到后端執(zhí)行。后端管理自己的線程,這些線程不斷收集和執(zhí)行排隊(duì)的任務(wù)。請(qǐng)注意,要使其正常工作,后端必須能夠跟蹤計(jì)算圖中各個(gè)步驟之間的依賴關(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.

pYYBAGR3JV2AP9YmAAMyVzf4gz4123.png

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

讓我們看另一個(gè)玩具示例以更好地理解依賴關(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.]])

pYYBAGR9OpWAYqN7AABuMUC0sRc200.svg

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

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

pYYBAGR9OpeAW4-ZAAF-uY5QXNk814.svg

圖 13.2.3前后端交互。

13.2.2。障礙和阻滯劑

有許多操作會(huì)強(qiáng)制 Python 等待完成:

最明顯的npx.waitall()是等待所有計(jì)算完成,而不管計(jì)算指令何時(shí)發(fā)出。在實(shí)踐中,除非絕對(duì)必要,否則使用此運(yùn)算符不是一個(gè)好主意,因?yàn)樗鼤?huì)導(dǎo)致性能不佳。

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

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

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

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

頻繁地將少量數(shù)據(jù)從 MXNet 的范圍復(fù)制到 NumPy 并返回可能會(huì)破壞原本高效代碼的性能,因?yàn)槊總€(gè)此類操作都需要計(jì)算圖來(lái)評(píng)估獲得相關(guān)術(shù)語(yǔ)所需的所有中間結(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。改進(jìn)計(jì)算

在高度多線程的系統(tǒng)上(即使是普通筆記本電腦也有 4 個(gè)或更多線程,而在多插槽服務(wù)器上,這個(gè)數(shù)字可能超過(guò) 256),調(diào)度操作的開銷會(huì)變得很大。這就是為什么非常需要異步和并行進(jìn)行計(jì)算和調(diào)度的原因。為了說(shuō)明這樣做的好處,讓我們看看如果我們將變量遞增 1 多次(順序或異步)會(huì)發(fā)生什么。我們通過(guò)wait_to_read在每次添加之間插入一個(gè)屏障來(lái)模擬同步執(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++后端線程之間的一個(gè)稍微簡(jiǎn)化的交互可以概括如下: 1. 前端命令后端將計(jì)算任務(wù)插入到隊(duì)列中。1. 后端從隊(duì)列中接收計(jì)算任務(wù)并進(jìn)行實(shí)際計(jì)算。1. 后端將計(jì)算結(jié)果返回給前端。假設(shè)這三個(gè)階段的持續(xù)時(shí)間是y = x + 1t1,t2和t3, 分別。如果我們不使用異步編程,執(zhí)行 10000 次計(jì)算所花費(fèi)的總時(shí)間大約是10000(t1+t2+t3). 如果使用異步編程,執(zhí)行10000次計(jì)算的總時(shí)間可以減少到t1+10000t2+t3(假設(shè) 10000t2>9999t1), 因?yàn)榍岸瞬槐氐却蠖朔祷孛總€(gè)循環(huán)的計(jì)算結(jié)果。

13.2.4。概括

深度學(xué)習(xí)框架可以將 Python 前端與執(zhí)行后端分離。這允許將命令快速異步插入后端??和相關(guān)的并行性。

異步會(huì)導(dǎo)致響應(yīng)相當(dāng)靈敏的前端。但是,請(qǐng)注意不要使任務(wù)隊(duì)列過(guò)滿,因?yàn)檫@可能會(huì)導(dǎo)致過(guò)多的內(nèi)存消耗。建議對(duì)每個(gè) minibatch 進(jìn)行同步,以保持前端和后端大致同步。

芯片供應(yīng)商提供復(fù)雜的性能分析工具,以更細(xì)致地了解深度學(xué)習(xí)的效率。

請(qǐng)注意,從 MXNet 的內(nèi)存管理轉(zhuǎn)換為 Python 將強(qiáng)制后端等待特定變量準(zhǔn)備就緒。print,asnumpy和等函數(shù)item都有這個(gè)效果。這可能是可取的,但不小心使用同步可能會(huì)破壞性能。

13.2.5。練習(xí)

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 異步
    +關(guān)注

    關(guān)注

    0

    文章

    62

    瀏覽量

    18018
  • pytorch
    +關(guān)注

    關(guān)注

    2

    文章

    795

    瀏覽量

    13019
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    PyTorch如何入門

    PyTorch 入門實(shí)戰(zhàn)(一)——Tensor
    發(fā)表于 06-01 09:58

    pytorch到RK1808計(jì)算棒的部署liuche流程是如何去完成的

    pytorch到RK1808計(jì)算棒的部署liuche流程是如何去完成的?
    發(fā)表于 02-15 06:04

    Pytorch AI語(yǔ)音助手

    想做一個(gè)Pytorch AI語(yǔ)音助手,有沒(méi)有好的思路呀?
    發(fā)表于 03-06 13:00

    通過(guò)Cortex來(lái)非常方便的部署PyTorch模型

    的機(jī)器學(xué)習(xí)框架是建立在 PyTorch 上的。在 ML 的幾乎任何領(lǐng)域,從計(jì)算機(jī)視覺(jué)到 NLP 再到計(jì)算生物學(xué),你都會(huì)發(fā)現(xiàn) PyTorch 在前沿為實(shí)驗(yàn)提供能量。然而,最自然的問(wèn)題是如
    發(fā)表于 11-01 15:25

    基于PyTorch的深度學(xué)習(xí)入門教程之PyTorch簡(jiǎn)單知識(shí)

    計(jì)算 Part3:使用PyTorch構(gòu)建一個(gè)神經(jīng)網(wǎng)絡(luò) Part4:訓(xùn)練一個(gè)神經(jīng)網(wǎng)絡(luò)分類器 Part5:數(shù)據(jù)并行化 本文是關(guān)于Part1的內(nèi)容。 Part1:PyTorch簡(jiǎn)單知識(shí) PyTorc
    的頭像 發(fā)表于 02-16 15:20 ?2154次閱讀

    基于PyTorch的深度學(xué)習(xí)入門教程之PyTorch的自動(dòng)梯度計(jì)算

    計(jì)算 Part3:使用PyTorch構(gòu)建一個(gè)神經(jīng)網(wǎng)絡(luò) Part4:訓(xùn)練一個(gè)神經(jīng)網(wǎng)絡(luò)分類器 Part5:數(shù)據(jù)并行化 本文是關(guān)于Part2的內(nèi)容。 Part2:PyTorch的自動(dòng)梯度計(jì)算
    的頭像 發(fā)表于 02-16 15:26 ?1924次閱讀

    PyTorch 的 Autograd 機(jī)制和使用

    PyTorch 作為一個(gè)深度學(xué)習(xí)平臺(tái),在深度學(xué)習(xí)任務(wù)中比 NumPy 這個(gè)科學(xué)計(jì)算庫(kù)強(qiáng)在哪里呢?我覺(jué)得一是 PyTorch 提供了自動(dòng)求導(dǎo)機(jī)制,二是對(duì) GPU 的支持。由此可見,自動(dòng)求導(dǎo) (autograd) 是
    的頭像 發(fā)表于 08-15 09:37 ?1004次閱讀

    PyTorch構(gòu)建自己一種易用的計(jì)算圖結(jié)構(gòu)

    PNNX項(xiàng)目 PyTorch Neural Network eXchange(PNNX)是PyTorch模型互操作性的開放標(biāo)準(zhǔn).
    的頭像 發(fā)表于 02-01 14:26 ?1017次閱讀

    Wolfram語(yǔ)言與Mathematica 13.2版本(2)

    除了能夠計(jì)算天文事物之外,版本13.2 還包括可視化天文事物的第一步。在后續(xù)版本中將有更多關(guān)于此的內(nèi)容。但是版本13.2 已經(jīng)具有一些強(qiáng)大的功能。
    的頭像 發(fā)表于 02-13 10:38 ?451次閱讀

    PyTorch教程5.3之前向傳播、反向傳播和計(jì)算

    電子發(fā)燒友網(wǎng)站提供《PyTorch教程5.3之前向傳播、反向傳播和計(jì)算圖.pdf》資料免費(fèi)下載
    發(fā)表于 06-05 15:36 ?0次下載
    <b class='flag-5'>PyTorch</b>教程5.3之前向傳播、反向傳播和<b class='flag-5'>計(jì)算</b>圖

    PyTorch教程13.2異步計(jì)算

    電子發(fā)燒友網(wǎng)站提供《PyTorch教程13.2異步計(jì)算.pdf》資料免費(fèi)下載
    發(fā)表于 06-05 14:46 ?0次下載
    <b class='flag-5'>PyTorch</b>教程<b class='flag-5'>13.2</b>之<b class='flag-5'>異步</b><b class='flag-5'>計(jì)算</b>

    PyTorch教程19.3之異步隨機(jī)搜索

    電子發(fā)燒友網(wǎng)站提供《PyTorch教程19.3之異步隨機(jī)搜索.pdf》資料免費(fèi)下載
    發(fā)表于 06-05 10:43 ?0次下載
    <b class='flag-5'>PyTorch</b>教程19.3之<b class='flag-5'>異步</b>隨機(jī)搜索

    深度學(xué)習(xí)框架pytorch入門與實(shí)踐

    的。PyTorch是一個(gè)開源的深度學(xué)習(xí)框架,在深度學(xué)習(xí)領(lǐng)域得到了廣泛應(yīng)用。本文將介紹PyTorch框架的基本知識(shí)、核心概念以及如何在實(shí)踐中使用PyTorch框架。 一、PyTorch
    的頭像 發(fā)表于 08-17 16:03 ?1469次閱讀

    深度學(xué)習(xí)框架pytorch介紹

    深度學(xué)習(xí)框架pytorch介紹 PyTorch是由Facebook創(chuàng)建的開源機(jī)器學(xué)習(xí)框架,其中TensorFlow是完全基于數(shù)據(jù)流圖的。它是一個(gè)使用動(dòng)態(tài)計(jì)算圖的框架,允許用戶更靈活地定義和修改模型
    的頭像 發(fā)表于 08-17 16:10 ?1554次閱讀

    PyTorch的介紹與使用案例

    PyTorch是一個(gè)基于Python的開源機(jī)器學(xué)習(xí)庫(kù),它主要面向深度學(xué)習(xí)和科學(xué)計(jì)算領(lǐng)域。PyTorch由Meta Platforms(原Facebook)的人工智能研究團(tuán)隊(duì)開發(fā),并逐漸發(fā)展成為深度
    的頭像 發(fā)表于 07-10 14:19 ?234次閱讀