動手學深度學習12.1. 編譯器和解釋器-筆記練習(PyTorch)

以下內容為結合李沐老師的課程和教材補充的學習筆記,以及對課后練習的一些思考,自留回顧,也供同學之人交流參考。

本節課程地址:無

本節教材地址:12.1. 編譯器和解釋器 — 動手學深度學習 2.0.0 documentation

本節開源代碼:...>d2l-zh>pytorch>chapter_optimization>hybridize.ipynb


編譯器和解釋器

目前為止,本書主要關注的是命令式編程(imperative programming)。 命令式編程使用諸如print、“+”和if之類的語句來更改程序的狀態。 考慮下面這段簡單的命令式程序:

def add(a, b):return a + bdef fancy_func(a, b, c, d):e = add(a, b)f = add(c, d)g = add(e, f)return gprint(fancy_func(1, 2, 3, 4))

輸出結果:
10

Python是一種解釋型語言(interpreted language)。因此,當對上面的fancy_func函數求值時,它按順序執行函數體的操作。也就是說,它將通過對e = add(a, b)求值,并將結果存儲為變量e,從而更改程序的狀態。接下來的兩個語句f = add(c, d)g = add(e, f)也將執行類似地操作,即執行加法計算并將結果存儲為變量。 圖12.1.1 說明了數據流。

盡管命令式編程很方便,但可能效率不高。一方面原因,Python會單獨執行這三個函數的調用,而沒有考慮add函數在fancy_func中被重復調用。如果在一個GPU(甚至多個GPU)上執行這些命令,那么Python解釋器產生的開銷可能會非常大。此外,它需要保存ef的變量值,直到fancy_func中的所有語句都執行完畢。這是因為程序不知道在執行語句e = add(a, b)f = add(c, d)之后,其他部分是否會使用變量ef

符號式編程

考慮另一種選擇符號式編程(symbolic programming),即代碼通常只在完全定義了過程之后才執行計算。這個策略被多個深度學習框架使用,包括Theano和TensorFlow(后者已經獲得了命令式編程的擴展)。一般包括以下步驟:

  1. 定義計算流程;
  2. 將流程編譯成可執行的程序;
  3. 給定輸入,調用編譯好的程序執行。

這將允許進行大量的優化。首先,在大多數情況下,我們可以跳過Python解釋器。從而消除因為多個更快的GPU與單個CPU上的單個Python線程搭配使用時產生的性能瓶頸。其次,編譯器可以將上述代碼優化和重寫為print((1 + 2) + (3 + 4))甚至print(10)。因為編譯器在將其轉換為機器指令之前可以看到完整的代碼,所以這種優化是可以實現的。例如,只要某個變量不再需要,編譯器就可以釋放內存(或者從不分配內存),或者將代碼轉換為一個完全等價的片段。下面,我們將通過模擬命令式編程來進一步了解符號式編程的概念。

def add_():return '''
def add(a, b):return a + b
'''def fancy_func_():return '''
def fancy_func(a, b, c, d):e = add(a, b)f = add(c, d)g = add(e, f)return g
'''def evoke_():return add_() + fancy_func_() + 'print(fancy_func(1, 2, 3, 4))'prog = evoke_()
print(prog)
# compile函數將字符串prog編譯為代碼對象
# 第一個參數是代碼字符串,第二個參數是文件名(空字符串意味著代碼不是從文件中讀取的),
# 第三個參數是模式,'exec'表示代碼是一個可執行的程序
y = compile(prog, '', 'exec')
# 用exec函數執行編譯后的代碼對象
exec(y)

輸出結果:
def add(a, b):
return a + b

def fancy_func(a, b, c, d):
e = add(a, b)
f = add(c, d)
g = add(e, f)
return g
print(fancy_func(1, 2, 3, 4))
10

命令式(解釋型)編程和符號式編程的區別如下:

  • 命令式編程更容易使用。在Python中,命令式編程的大部分代碼都是簡單易懂的。命令式編程也更容易調試,這是因為無論是獲取和打印所有的中間變量值,或者使用Python的內置調試工具都更加簡單;
  • 符號式編程運行效率更高,更易于移植。符號式編程更容易在編譯期間優化代碼,同時還能夠將程序移植到與Python無關的格式中,從而允許程序在非Python環境中運行,避免了任何潛在的與Python解釋器相關的性能問題。

混合式編程

歷史上,大部分深度學習框架都在命令式編程與符號式編程之間進行選擇。例如,Theano、TensorFlow(靈感來自前者)、Keras和CNTK采用了符號式編程。相反地,Chainer和PyTorch采取了命令式編程。在后來的版本更新中,TensorFlow2.0和Keras增加了命令式編程。

如上所述,PyTorch是基于命令式編程并且使用動態計算圖。為了能夠利用符號式編程的可移植性和效率,開發人員思考能否將這兩種編程模型的優點結合起來,于是就產生了torchscript。torchscript允許用戶使用純命令式編程進行開發和調試,同時能夠將大多數程序轉換為符號式程序,以便在需要產品級計算性能和部署時使用。

Sequential的混合式編程

要了解混合式編程的工作原理,最簡單的方法是考慮具有多層的深層網絡。按照慣例,Python解釋器需要執行所有層的代碼來生成一條指令,然后將該指令轉發到CPU或GPU。對于單個的(快速的)計算設備,這不會導致任何重大問題。另一方面,如果我們使用先進的8-GPU服務器,比如AWS P3dn.24xlarge實例,Python將很難讓所有的GPU都保持忙碌。在這里,瓶頸是單線程的Python解釋器。讓我們看看如何通過將Sequential替換為HybridSequential來解決代碼中這個瓶頸。首先,我們定義一個簡單的多層感知機。

import torch
from torch import nn
from d2l import torch as d2l# 生產網絡的工廠模式
def get_net():net = nn.Sequential(nn.Linear(512, 256),nn.ReLU(),nn.Linear(256, 128),nn.ReLU(),nn.Linear(128, 2))return netx = torch.randn(size=(1, 512))
net = get_net()
net(x)

輸出結果:
tensor([[ 0.0913, -0.0081]], grad_fn=<AddmmBackward0>)

通過使用torch.jit.script函數來轉換模型,我們就有能力編譯和優化多層感知機中的計算,而模型的計算結果保持不變。

net = torch.jit.script(net)
net(x)

輸出結果:
tensor([[ 0.0913, -0.0081]], grad_fn=<AddmmBackward0>)

我們編寫與之前相同的代碼,再使用torch.jit.script簡單地轉換模型,當完成這些任務后,網絡就將得到優化(我們將在下面對性能進行基準測試)。

通過混合式編程加速

為了證明通過編譯獲得了性能改進,我們比較了混合編程前后執行net(x)所需的時間。讓我們先定義一個度量時間的類,它在本章中在衡量(和改進)模型性能時將非常有用。

#@save
class Benchmark:"""用于測量運行時間"""def __init__(self, description='Done'):self.description = descriptiondef __enter__(self):self.timer = d2l.Timer()return selfdef __exit__(self, *args):print(f'{self.description}: {self.timer.stop():.4f} sec')

現在我們可以調用網絡兩次,一次使用torchscript,一次不使用torchscript。

net = get_net()
with Benchmark('無torchscript'):for i in range(1000): net(x)net = torch.jit.script(net)
with Benchmark('有torchscript'):for i in range(1000): net(x)

輸出結果:
無torchscript: 1.6907 sec
有torchscript: 1.6595 sec

如以上結果所示,在nn.Sequential的實例被函數torch.jit.script腳本化后,通過使用符號式編程提高了計算性能。

序列化

編譯模型的好處之一是我們可以將模型及其參數序列化(保存)到磁盤。這允許這些訓練好的模型部署到其他設備上,并且還能方便地使用其他前端編程語言。同時,通常編譯模型的代碼執行速度也比命令式編程更快。讓我們看看save的實際功能。

net.save('my_mlp')
!ls -lh my_mlp*

輸出結果:
-rw-rw-r--. 1 huida SharedUsers 652K May 6 14:12 my_mlp

小結

  • 命令式編程使得新模型的設計變得容易,因為可以依據控制流編寫代碼,并擁有相對成熟的Python軟件生態。
  • 符號式編程要求我們先定義并且編譯程序,然后再執行程序,其好處是提高了計算性能。

練習

  1. 回顧前幾章中感興趣的模型,能提高它們的計算性能嗎?

解:
以LeNet模型為例,使用torch.jit.script函數可以提高其網絡計算性能。
代碼如下:

# LeNet
net = nn.Sequential(nn.Conv2d(1, 6, kernel_size=5, padding=2), nn.Sigmoid(),nn.AvgPool2d(kernel_size=2, stride=2),nn.Conv2d(6, 16, kernel_size=5), nn.Sigmoid(),nn.AvgPool2d(kernel_size=2, stride=2),nn.Flatten(),nn.Linear(16 * 5 * 5, 120), nn.Sigmoid(),nn.Linear(120, 84), nn.Sigmoid(),nn.Linear(84, 10))X = torch.rand(size=(1, 1, 28, 28), dtype=torch.float32)with Benchmark('無torchscript'):for i in range(1000): net(X)net = torch.jit.script(net)
with Benchmark('有torchscript'):for i in range(1000): net(X)

輸出結果:
無torchscript: 3.2212 sec
有torchscript: 2.8837 sec

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/79725.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/79725.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/79725.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[java八股文][Java并發編程面試篇]并發安全

juc包下你常用的類&#xff1f; 線程池相關&#xff1a; ThreadPoolExecutor&#xff1a;最核心的線程池類&#xff0c;用于創建和管理線程池。通過它可以靈活地配置線程池的參數&#xff0c;如核心線程數、最大線程數、任務隊列等&#xff0c;以滿足不同的并發處理需求。Exe…

VMware搭建ubuntu保姆級教程

目錄 VMware Ubuntu 虛擬機配置指南 創建虛擬機 下載 Ubuntu ISO 新建虛擬機 網絡配置&#xff08;雙網卡模式&#xff09; 共享文件夾設置 SSH 遠程訪問配置 VMware Ubuntu 虛擬機配置指南 創建虛擬機 下載 Ubuntu ISO 【可添加我獲取】 官網&#xff1a;Get Ubunt…

馮諾依曼結構與哈佛架構深度解析

一、馮諾依曼結構&#xff08;Von Neumann Architecture&#xff09; 1.1 核心定義 由約翰馮諾依曼提出&#xff0c;程序指令與數據共享同一存儲空間和總線&#xff0c;通過分時復用實現存取。 存儲器總帶寬 指令帶寬 數據帶寬 即&#xff1a;B_mem f_clk W_data f_…

C/C++工程中的Plugin機制設計與Python實現

C/C工程中的Plugin機制設計與Python實現 1. Plugin機制設計概述 在C/C工程中實現Plugin機制通常需要以下幾個關鍵組件&#xff1a; Plugin接口定義&#xff1a;定義統一的接口規范動態加載機制&#xff1a;運行時加載動態庫注冊機制&#xff1a;Plugin向主程序注冊自己通信機…

node-sass安裝失敗解決方案

1、python環境問題 Error: Cant find Python executable "python", you can set the PYTHON env variable. 提示找不到python2.7版本&#xff0c; 方法一&#xff1a;可安裝一個python2.7或引用其他已安裝的python2.7 通過設置環境變量可以解決&#xff1b; 方法二&…

Netty高并發物聯網通信服務器實戰:協議優化與性能調優指南

目錄 1.總體設計 2.自定義協議設計(簡單版) 3.消息類型(1字節) 4.項目結構 5.核心功能代碼 (1)pom.xml(Maven依賴) (2)IotServer.java(服務器啟動器) (3)IotServerInitializer.java(Pipeline初始化) (4)DeviceChannelManager.java(設備連接管理器)…

多模態大語言模型arxiv論文略讀(六十)

Cantor: Inspiring Multimodal Chain-of-Thought of MLLM ?? 論文標題&#xff1a;Cantor: Inspiring Multimodal Chain-of-Thought of MLLM ?? 論文作者&#xff1a;Timin Gao, Peixian Chen, Mengdan Zhang, Chaoyou Fu, Yunhang Shen, Yan Zhang, Shengchuan Zhang, Xi…

面試常問系列(一)-神經網絡參數初始化-之自注意力機制為什么除以根號d而不是2*根號d或者3*根號d

首先先羅列幾個參考文章&#xff0c;大家之后可以去看看&#xff0c;加深理解&#xff1a; 面試常問系列(一)-神經網絡參數初始化面試常問系列(一)-神經網絡參數初始化之自注意力機制_注意力機制的參數初始化怎么做-CSDN博客面試常問系列(一)-神經網絡參數初始化-之-softmax-C…

第5篇:EggJS中間件開發與實戰應用

在Web開發中&#xff0c;中間件&#xff08;Middleware&#xff09;是處理HTTP請求和響應的核心機制之一。EggJS基于Koa的洋蔥模型實現了高效的中間件機制&#xff0c;本文將深入探討中間件的執行原理、開發實踐以及常見問題解決方案。 一、中間件執行機制與洋蔥模型 1. 洋蔥模…

樹狀結構轉換工具類

項目中使用了很多樹狀結構&#xff0c;為了方便使用開發一個通用的工具類。 使用工具類的時候寫一個類基礎BaseNode&#xff0c;如果有個性化字段添加到類里面&#xff0c;然后就可以套用工具類。 工具類會將id和pid做關聯返回一個樹狀結構的集合。 使用了hutool的工具包判空…

【Python】--裝飾器

裝飾器&#xff08;Decorator&#xff09;本質上是一個返回函數的函數 主要作用是&#xff1a;在不修改原函數代碼的前提下&#xff0c;給函數增加額外的功能 比如&#xff1a;增加業務&#xff0c;日志記錄、權限驗證、執行時間統計、緩存等場景 my_decorator def func():pas…

AI教你學VUE——Gemini版

前端開發學習路線圖 (針對編程新手&#xff0c;主攻 Vue 框架) 總原則&#xff1a;先夯實基礎&#xff0c;再深入框架。 想象一下建房子&#xff0c;地基不牢&#xff0c;上面的高樓&#xff08;框架&#xff09;是蓋不起來的。HTML、CSS、JavaScript 就是前端的地基。 階段一…

神經網絡中之多類別分類:從基礎到高級應用

神經網絡中之多類別分類&#xff1a;從基礎到高級應用 摘要 在機器學習領域&#xff0c;多類別分類是解決復雜問題的關鍵技術之一。本文深入探討了神經網絡在多類別分類中的應用&#xff0c;從基礎的二元分類擴展到一對多和一對一分類方法。我們詳細介紹了 softmax 函數的原理…

Go Web 后臺管理系統項目詳解

Go Web 后臺管理系統項目詳解 一、背景介紹 這是一個基于 Go 語言開發的 Web 后臺管理系統&#xff0c;為筆者學習期間練手之作&#xff0c;較為粗糙 二、技術架構 后端 語言 &#xff1a;采用 Go 語言&#xff08;Golang&#xff09;編寫&#xff0c;因其簡潔高效、并發能…

【Python系列】Python 中的 HTTP 請求處理

&#x1f49d;&#x1f49d;&#x1f49d;歡迎來到我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里可以感受到一份輕松愉快的氛圍&#xff0c;不僅可以獲得有趣的內容和知識&#xff0c;也可以暢所欲言、分享您的想法和見解。 推薦:kwan 的首頁,持續學…

OS7.【Linux】基本指令入門(6)

目錄 1.zip和unzip 配置指令 使用 兩個名詞:打包和壓縮 打包 壓縮 Linux下的操作演示 壓縮和解壓縮文件 壓縮和解壓縮目錄 -d選項 2.tar Linux下的打包和壓縮方案簡介 czf選項 xzf選項 -C選項 tzf選項 3.bc 4.uname 不帶選項的uname -a選項 -r選項 -v選項…

windows系統 壓力測試技術

一、CPU壓測模擬 工具&#xff1a;CpuStres v2.0 官網&#xff1a;https://learn.microsoft.com/en-us/sysinternals/downloads/cpustres 功能&#xff1a;是一個工具類&#xff0c;用來模擬在一個進程中啟動最多64個線程&#xff0c;且可以獨立控制任何一個線程的啟動/暫停、…

64.搜索二維矩陣

給你一個滿足下述兩條屬性的 m x n 整數矩陣&#xff1a; 每行中的整數從左到右按非嚴格遞增順序排列。每行的第一個整數大于前一行的最后一個整數。 給你一個整數 target &#xff0c;如果 target 在矩陣中&#xff0c;返回 true &#xff1b;否則&#xff0c;返回 false 。 示…

在 PyTorch 中借助 GloVe 詞嵌入完成情感分析

一. Glove 詞嵌入原理 GloVe是一種學習詞嵌入的方法&#xff0c;它希望擬合給定上下文單詞i時單詞j出現的次數。使用的誤差函數為&#xff1a; 其中N是詞匯表大小&#xff0c;是線性層參數&#xff0c; 是詞嵌入。f(x)是權重項&#xff0c;用于平衡不同頻率的單詞對誤差的影響…

kotlin中 熱流 vs 冷流 的本質區別

&#x1f525; 冷流&#xff08;Cold Flow&#xff09; vs 熱流&#xff08;Hot Flow&#xff09;區別 特性冷流&#xff08;Cold Flow&#xff09;熱流&#xff08;Hot Flow&#xff09;數據生產時機每次 collect 才開始執行啟動時就開始生產、始終運行生命周期與 collect 者…