最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

利用Psyco提升Python運(yùn)行速度

 更新時(shí)間:2014年12月24日 17:18:32   投稿:mdxy-dxy  
這篇文章主要介紹了利用Psyco提升Python運(yùn)行速度,需要的朋友可以參考下

Psyco 是嚴(yán)格地在 Python 運(yùn)行時(shí)進(jìn)行操作的。也就是說(shuō),Python 源代碼是通過(guò) python 命令編譯成字節(jié)碼的,所用的方式和以前完全相同(除了為調(diào)用 Psyco 而添加的幾個(gè) import 語(yǔ)句和函數(shù)調(diào)用)。但是當(dāng) Python 解釋器運(yùn)行應(yīng)用程序時(shí),Psyco 會(huì)不時(shí)地檢查,看是否能用一些專門的機(jī)器代碼去替換常規(guī)的 Python 字節(jié)碼操作。這種專門的編譯和 Java 即時(shí)編譯器所進(jìn)行的操作非常類似(一般地說(shuō),至少是這樣),并且是特定于體系結(jié)構(gòu)的。到現(xiàn)在為止,Psyco 只可用于 i386 CPU 體系結(jié)構(gòu)。Psyco 的妙處在于可以使用您一直在編寫(xiě)的 Python 代碼(完全一樣?。?,卻可以讓它運(yùn)行得更快。

Psyco 是如何工作的

要完全理解 Psyco,您可能需要很好地掌握 Python 解釋器的 eval_frame() 函數(shù)和 i386 匯編語(yǔ)言。遺憾的是,我自己不能對(duì)其中任何一項(xiàng)發(fā)表專家性的意見(jiàn) - 但是我想我可以大致不差地概述 Psyco。
在常規(guī)的 Python 中,eval_frame() 函數(shù)是 Python 解釋器的內(nèi)循環(huán)。eval_frame() 函數(shù)主要察看執(zhí)行上下文中的當(dāng)前字節(jié)碼,并將控制向外切換到一個(gè)適合實(shí)現(xiàn)該字節(jié)碼的函數(shù)。支持函數(shù)將做什么的具體細(xì)節(jié)通常取決于保存在內(nèi)存中的各種 Python 對(duì)象的狀態(tài)。簡(jiǎn)單點(diǎn)說(shuō),添加 Python 對(duì)象“2”和“3”和添加對(duì)象“5”和“6”會(huì)產(chǎn)生不同的結(jié)果,但是這兩個(gè)操作都以類似的方式分派。
Psyco 用復(fù)合求值單元替代 eval_frame() 函數(shù)。Psyco 有幾種方法可以用來(lái)改進(jìn) Python 所進(jìn)行的操作。首先,Psyco 將操作編譯成有點(diǎn)優(yōu)化的機(jī)器碼;由于機(jī)器碼需要完成的工作和 Python 的分派函數(shù)所要做的事一樣,所以其本身只有些許改進(jìn)。而且,Psyco 編譯中的“專門的”內(nèi)容不僅僅是對(duì) Python 字節(jié)碼的選擇,Psyco 也要對(duì)執(zhí)行上下文中已知的變量值進(jìn)行專門化。例如,在類似于下面的代碼中,變量 x 在循環(huán)持續(xù)時(shí)間內(nèi)是可知的:

復(fù)制代碼 代碼如下:

x = 5
l = []
for i in range(1000):
l.append(x*i)

該段代碼的優(yōu)化版本不需要用“x 變量/對(duì)象的內(nèi)容”乘每個(gè) i,與之相比,簡(jiǎn)單地用 5 乘以每個(gè) i 所用的開(kāi)銷較少,省略了查找/間接引用這一步。
除為小型操作創(chuàng)建特定于 i386 的代碼之外,Psyco 還高速緩存這個(gè)已編譯的機(jī)器碼以備今后重用。如果 Psyco 能夠識(shí)別出特定的操作和早先所執(zhí)行的(“專門化的”)操作一樣,那么,它就能依靠這個(gè)高速緩存的代碼而不需要再次編譯代碼段。這樣就節(jié)省了一些時(shí)間。
但是,Psyco 中真正省時(shí)的原因在于 Psyco 將操作分成三個(gè)不同的級(jí)別。對(duì)于 Psyco,有“運(yùn)行時(shí)”、“編譯時(shí)”和“虛擬時(shí)”變量。Psyco 根據(jù)需要提高和降低變量的級(jí)別。運(yùn)行時(shí)變量只是常規(guī) Python 解釋器處理的原始字節(jié)碼和對(duì)象結(jié)構(gòu)。一旦 Psyco 將操作編譯成機(jī)器碼,那么編譯時(shí)變量就會(huì)在機(jī)器寄存器和可直接訪問(wèn)的內(nèi)存位置中表示。
最有意思的級(jí)別是虛擬時(shí)變量。在內(nèi)部,一個(gè) Python 變量就是一個(gè)有許多成員組成的完整結(jié)構(gòu) - 即使當(dāng)對(duì)象只代表一個(gè)整數(shù)時(shí)也是如此。Psyco 虛擬時(shí)變量代表了需要時(shí)可能會(huì)被構(gòu)建的 Python 對(duì)象,但是這些對(duì)象的詳細(xì)信息在它們成為 Python 對(duì)象之前是被忽略的。例如,考慮如下賦值:
x = 15 * (14 + (13 - (12 / 11)))
標(biāo)準(zhǔn)的 Python 會(huì)構(gòu)建和破壞許多對(duì)象以計(jì)算這個(gè)值。構(gòu)建一個(gè)完整的整數(shù)對(duì)象以保存 (12/11) 這個(gè)值;然后從臨時(shí)對(duì)象的結(jié)構(gòu)中“拉”出一個(gè)值并用它計(jì)算新的臨時(shí)對(duì)象 (13-PyInt)。而 Psyco 跳過(guò)這些對(duì)象,只計(jì)算這些值,因?yàn)樗馈叭绻枰?,可以從值?chuàng)建一個(gè)對(duì)象。

使用 Psyco

解釋 Psyco 相對(duì)比較困難,但是使用 Psyco 就非常容易了?;旧?,其全部?jī)?nèi)容就是告訴 Psyco 模塊哪個(gè)函數(shù)/方法要“專門化”。任何 Python 函數(shù)和類本身的代碼都不需進(jìn)行更改。
有幾種方法可以指定 Psyco 應(yīng)該做什么。“獵槍(shotgun)”方法使得隨處都可使用 Psyco 即時(shí)操作。要做到這點(diǎn),把下列行置于模塊頂端:

復(fù)制代碼 代碼如下:

import psyco ; psyco.jit()
from psyco.classes import *

第一行告訴 Psyco 對(duì)所有全局函數(shù)“發(fā)揮其魔力”。第二行(在 Python 2.2 及以上版本中)告訴 Psyco 對(duì)類方法執(zhí)行相同的操作。為了更精確地確定 Psyco 的行為,可以使用下列命令:
psyco.bind(somefunc) # or method, class
newname = psyco.proxy(func)
第二種形式把 func 作為標(biāo)準(zhǔn)的 Python 函數(shù),但是優(yōu)化了涉及 newname 的調(diào)用。除了測(cè)試和調(diào)試之外的幾乎所有的情況下,您都將使用 psyco.bind() 形式。

Psyco 的性能

盡管 Psyco 如此神奇,使用它仍然需要一點(diǎn)思考和測(cè)試。主要是要明白 Psyco 對(duì)于處理多次循環(huán)的塊是很有用的,而且它知道如何優(yōu)化涉及整數(shù)和浮點(diǎn)數(shù)的操作。對(duì)于非循環(huán)函數(shù)和其它類型對(duì)象的操作,Psyco 多半只會(huì)增加其分析和內(nèi)部編譯的開(kāi)銷。而且,對(duì)于含有大量函數(shù)和類的應(yīng)用程序來(lái)說(shuō),在整個(gè)應(yīng)用程序范圍啟用 Psyco,會(huì)在機(jī)器碼編譯和用于這一高速緩存的內(nèi)存使用方面增加大量的負(fù)擔(dān)。有選擇性地綁定那些可以從 Psyco 的優(yōu)化中獲得最大收益的函數(shù),這樣會(huì)好得多。
我以十分幼稚的方式開(kāi)始了我的測(cè)試過(guò)程。我僅僅考慮了我近來(lái)運(yùn)行的、但還未考慮加速的應(yīng)用程序。想到的第一個(gè)示例是用來(lái)將我即將出版的書(shū)稿(Text Processing in Python)轉(zhuǎn)換成 LaTeX 格式的文本操作程序。該應(yīng)用程序使用了一些字符串方法、一些正則表達(dá)式和一些主要由正則表達(dá)式和字符串匹配所驅(qū)動(dòng)的程序邏輯。實(shí)際上將它用作 Psyco 的測(cè)試候選是很糟的選擇,但是我還是使用了,就這么開(kāi)始了。
第一遍測(cè)試中,我所做的就是將 psyco.jit() 添加到腳本頂端。這做起來(lái)一點(diǎn)都不費(fèi)力。遺憾的是,結(jié)果(意料當(dāng)中)很令人失望。原先腳本運(yùn)行要花費(fèi) 8.5 秒,經(jīng)過(guò) Psyco 的“加速”后它大概要運(yùn)行 12 秒。真差勁!我猜測(cè)大概是即時(shí)編譯所需的啟動(dòng)開(kāi)銷拖累了運(yùn)行時(shí)間。因此接下來(lái)我試著處理一個(gè)更大的輸入文件(由原來(lái)那個(gè)輸入文件的多個(gè)副本組成)。這次獲得了小小的成功,將運(yùn)行時(shí)間從 120 秒左右減到了 110 秒。幾次運(yùn)行中的加速效果比較一致,但是效果都不顯著。
本處理候選項(xiàng)的第二遍測(cè)試中。我只添加了 psyco.bind(main) 這一行,而不是添加一個(gè)總的 psyco.jit() 調(diào)用,因?yàn)?main() 函數(shù)確實(shí)要循環(huán)多次(但是僅利用了最少的整數(shù)運(yùn)算)。這里的結(jié)果名義上要比前面好。這種方法將正常的運(yùn)行時(shí)間削減了十分之幾秒,在較大的輸入版本的情況下削減了數(shù)秒鐘。但是仍然沒(méi)有引入矚目的結(jié)果發(fā)生(但也沒(méi)產(chǎn)生什么害處)。

為進(jìn)行更恰當(dāng)?shù)?Psyco 測(cè)試,我搜尋出我在以前的文章里編寫(xiě)的一些神經(jīng)網(wǎng)絡(luò)代碼(請(qǐng)參閱“參考資料”)。這個(gè)“代碼識(shí)別器(code_recognizer)”應(yīng)用程序可以經(jīng)“訓(xùn)練”用于識(shí)別不同編程語(yǔ)言編寫(xiě)的不同 ASCII 值的可能分布情況。類似于這樣的東西可能在猜測(cè)文件類型方面(比方說(shuō)丟失的網(wǎng)絡(luò)信息包)將很有用;但是,關(guān)于“訓(xùn)練”些什么,代碼實(shí)際上完全是通用的 - 它能很容易地學(xué)會(huì)識(shí)別面孔、聲音或潮汐模式。任何情況下,“代碼識(shí)別器”都基于 Python 庫(kù) bpnn,Psyco 4.0 分發(fā)版也包含(以修正的形式)了該庫(kù)作為測(cè)試用例。在本文中,對(duì)“代碼識(shí)別器”要重點(diǎn)了解它做了許多浮點(diǎn)運(yùn)算循環(huán)并花費(fèi)了很長(zhǎng)的運(yùn)行時(shí)間。這里我們已經(jīng)有了一個(gè)能用于 Psyco 測(cè)試的好的候選用例。
使用了一段時(shí)間后,我建立了有關(guān) Psyco 用法的一些詳細(xì)信息。對(duì)于這種只有少量類和函數(shù)的應(yīng)用程序,使用即時(shí)綁定還是目標(biāo)綁定沒(méi)有太大區(qū)別。但最佳的結(jié)果是,通過(guò)有選擇性地綁定最優(yōu)化類,仍可得到幾個(gè)百分點(diǎn)的改進(jìn)。然而,更值得注意的是要理解 Psyco 綁定的作用域,這一點(diǎn)很重要。
code_recognizer.py 腳本包括類似于下面的這些行:

從 bpnn 導(dǎo)入 NN
class NN2(NN):
# customized output methods, math core inherited
也就是說(shuō),從 Psyco 的觀點(diǎn)來(lái)看,有趣的事情在類 bpnn.NN 之中。把 psyco.jit() 或 psyco.bind(NN2) 添加到 code_recognizer.py 腳本中起不了什么作用。要使 Psyco 進(jìn)行期望的優(yōu)化,需要將 psyco.bind(NN) 添加到 code_recognizer.py 或者將 psyco.jit() 添加到 bpnn.py。與您可能假設(shè)的情況相反,即時(shí)優(yōu)化不在創(chuàng)建實(shí)例時(shí)或方法運(yùn)行時(shí)發(fā)生,而是在定義類的作用域內(nèi)發(fā)生。另外,綁定派生類不會(huì)專門化其從其它地方繼承的方法。
一旦找到適當(dāng)?shù)?Psyco 綁定的細(xì)微的詳細(xì)信息,那么加速效果是相當(dāng)明顯的。使用參考文章中提供的相同測(cè)試用例和訓(xùn)練方法(500 個(gè)訓(xùn)練模式,1000 個(gè)訓(xùn)練迭代),神經(jīng)網(wǎng)絡(luò)訓(xùn)練時(shí)間從 2000 秒左右減到了 600 秒左右 - 提速了 3 倍多。將迭代次數(shù)降到 10,加速的倍數(shù)也成比例降低(但對(duì)神經(jīng)網(wǎng)絡(luò)的識(shí)別能力無(wú)效),迭代的中間數(shù)值也會(huì)如此變化。
我發(fā)現(xiàn)使用兩行新代碼就能將運(yùn)行時(shí)間從超過(guò)半小時(shí)減到 10 分鐘左右,效果非常顯著。這種加速仍可能比 C 編寫(xiě)的類似應(yīng)用程序的速度慢,而且它肯定比幾個(gè)獨(dú)立的 Psyco 測(cè)試用例所反映出的 100 倍加速要慢。但是這種應(yīng)用程序是相當(dāng)“真實(shí)的”,而且在許多環(huán)境中這些改進(jìn)已經(jīng)是夠顯著的了。

相關(guān)文章

  • Tensorflow加載預(yù)訓(xùn)練模型和保存模型的實(shí)例

    Tensorflow加載預(yù)訓(xùn)練模型和保存模型的實(shí)例

    今天小編就為大家分享一篇Tensorflow加載預(yù)訓(xùn)練模型和保存模型的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • Python中Pyenv virtualenv插件的使用

    Python中Pyenv virtualenv插件的使用

    pyenv是管理python版本的工具。安裝pyenv后,可以管理各種python版本,并且各個(gè)版本的環(huán)境完全獨(dú)立,互不干擾。今天通過(guò)本文給大家分享Python中Pyenv virtualenv插件的使用,感興趣的朋友一起看看吧
    2021-06-06
  • PyTorch中torch.nn.Linear實(shí)例詳解

    PyTorch中torch.nn.Linear實(shí)例詳解

    torch.nn是包含了構(gòu)筑神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)基本元素的包,在這個(gè)包中可以找到任意的神經(jīng)網(wǎng)絡(luò)層,下面這篇文章主要給大家介紹了關(guān)于PyTorch中torch.nn.Linear的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • 詳解Python編程中對(duì)Monkey Patch猴子補(bǔ)丁開(kāi)發(fā)方式的運(yùn)用

    詳解Python編程中對(duì)Monkey Patch猴子補(bǔ)丁開(kāi)發(fā)方式的運(yùn)用

    Monkey Patch猴子補(bǔ)丁方式是指在不修改程序原本代碼的前提下,通過(guò)添加類或模塊等方式在程序運(yùn)行過(guò)程中加入代碼,下面就來(lái)進(jìn)一步詳解Python編程中對(duì)Monkey Patch猴子補(bǔ)丁開(kāi)發(fā)方式的運(yùn)用
    2016-05-05
  • 75條笑死人的知乎神回復(fù),用60行代碼就爬完了

    75條笑死人的知乎神回復(fù),用60行代碼就爬完了

    這篇文章主要介紹了python爬取知乎回復(fù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • python開(kāi)發(fā)之thread線程基礎(chǔ)實(shí)例入門

    python開(kāi)發(fā)之thread線程基礎(chǔ)實(shí)例入門

    這篇文章主要介紹了python開(kāi)發(fā)之thread線程基礎(chǔ),以三個(gè)實(shí)例形式分析了Python中thread線程的基本使用方法,涉及串行與并行程序的執(zhí)行原理及線程的操作技巧,需要的朋友可以參考下
    2015-11-11
  • Python 讀寫(xiě) Matlab Mat 格式數(shù)據(jù)的操作

    Python 讀寫(xiě) Matlab Mat 格式數(shù)據(jù)的操作

    這篇文章主要介紹了Python 讀寫(xiě) Matlab Mat 格式數(shù)據(jù)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-05-05
  • pymongo中g(shù)roup by的操作方法教程

    pymongo中g(shù)roup by的操作方法教程

    這篇文章主要給大家介紹了關(guān)于pymongo中g(shù)roup by的操作方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用pymongo具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • Cpython編譯后再使用Pyinstaller打包的詳細(xì)教程

    Cpython編譯后再使用Pyinstaller打包的詳細(xì)教程

    pyinstaller是一個(gè)第三方庫(kù),它能夠在Windows、Linux、 Mac OS X 等操作系統(tǒng)下將 Python 源文件打包,通過(guò)對(duì)源文件打包,這篇文章主要介紹了Cpython編譯后再使用Pyinstaller打包的詳細(xì)教程,需要的朋友可以參考下
    2023-11-11
  • 利用Python的Django框架生成PDF文件的教程

    利用Python的Django框架生成PDF文件的教程

    這篇文章主要介紹了利用Python的Django框架生成PDF文件的教程,用ReportLab API動(dòng)態(tài)生成PDF文件,需要的朋友可以參考下
    2015-07-07

最新評(píng)論

星子县| 莆田市| 胶南市| 墨玉县| 泾阳县| 利辛县| 凤凰县| 澄迈县| 六盘水市| 陇南市| 松潘县| 麦盖提县| 和平县| 田东县| 长沙市| 滦平县| 成武县| 平原县| 威远县| 凤台县| 浦江县| 嫩江县| 苍山县| 正宁县| 高安市| 长治市| 福安市| 鹿泉市| 宿州市| 东兰县| 高台县| 石楼县| 丰县| 新蔡县| 弥勒县| 沁水县| 东阿县| 临澧县| 吉安县| 渝北区| 彰化县|