午夜国产狂喷潮在线观看|国产AⅤ精品一区二区久久|中文字幕AV中文字幕|国产看片高清在线

    利用Psyco提升Python運(yùn)行速度
    來(lái)源:易賢網(wǎng) 閱讀:843 次 日期:2015-01-03 10:57:20
    溫馨提示:易賢網(wǎng)小編為您整理了“利用Psyco提升Python運(yùn)行速度”,方便廣大網(wǎng)友查閱!

    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í)地檢查,看是否能用一些專(zhuān)門(mén)的機(jī)器代碼去替換常規(guī)的 Python 字節(jié)碼操作。這種專(zhuān)門(mén)的編譯和 Java 即時(shí)編譯器所進(jìn)行的操作非常類(lèi)似(一般地說(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ā)表專(zhuān)家性的意見(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è)操作都以類(lèi)似的方式分派。

    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 編譯中的“專(zhuān)門(mén)的”內(nèi)容不僅僅是對(duì) Python 字節(jié)碼的選擇,Psyco 也要對(duì)執(zhí)行上下文中已知的變量值進(jìn)行專(zhuān)門(mén)化。例如,在類(lèi)似于下面的代碼中,變量 x 在循環(huán)持續(xù)時(shí)間內(nèi)是可知的:

    代碼如下:

    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)銷(xiāo)較少,省略了查找/間接引用這一步。

    除為小型操作創(chuàng)建特定于 i386 的代碼之外,Psyco 還高速緩存這個(gè)已編譯的機(jī)器碼以備今后重用。如果 Psyco 能夠識(shí)別出特定的操作和早先所執(zhí)行的(“專(zhuān)門(mén)化的”)操作一樣,那么,它就能依靠這個(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ù)/方法要“專(zhuān)門(mén)化”。任何 Python 函數(shù)和類(lèi)本身的代碼都不需進(jìn)行更改。

    有幾種方法可以指定 Psyco 應(yīng)該做什么?!矮C槍?zhuān)╯hotgun)”方法使得隨處都可使用 Psyco 即時(shí)操作。要做到這點(diǎn),把下列行置于模塊頂端:

    代碼如下:

    import psyco ; psyco.jit()

    from psyco.classes import *

    第一行告訴 Psyco 對(duì)所有全局函數(shù)“發(fā)揮其魔力”。第二行(在 Python 2.2 及以上版本中)告訴 Psyco 對(duì)類(lèi)方法執(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ù)和其它類(lèi)型對(duì)象的操作,Psyco 多半只會(huì)增加其分析和內(nèi)部編譯的開(kāi)銷(xiāo)。而且,對(duì)于含有大量函數(shù)和類(lèi)的應(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)銷(xiāo)拖累了運(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 值的可能分布情況。類(lèi)似于這樣的東西可能在猜測(cè)文件類(lèi)型方面(比方說(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ì)于這種只有少量類(lèi)和函數(shù)的應(yīng)用程序,使用即時(shí)綁定還是目標(biāo)綁定沒(méi)有太大區(qū)別。但最佳的結(jié)果是,通過(guò)有選擇性地綁定最優(yōu)化類(lèi),仍可得到幾個(gè)百分點(diǎn)的改進(jìn)。然而,更值得注意的是要理解 Psyco 綁定的作用域,這一點(diǎn)很重要。

    code_recognizer.py 腳本包括類(lèi)似于下面的這些行:

    從 bpnn 導(dǎo)入 NN

    class NN2(NN):

    # customized output methods, math core inherited

    也就是說(shuō),從 Psyco 的觀點(diǎn)來(lái)看,有趣的事情在類(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ā)生,而是在定義類(lèi)的作用域內(nèi)發(fā)生。另外,綁定派生類(lèi)不會(huì)專(zhuān)門(mén)化其從其它地方繼承的方法。

    一旦找到適當(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ě)的類(lèi)似應(yīng)用程序的速度慢,而且它肯定比幾個(gè)獨(dú)立的 Psyco 測(cè)試用例所反映出的 100 倍加速要慢。但是這種應(yīng)用程序是相當(dāng)“真實(shí)的”,而且在許多環(huán)境中這些改進(jìn)已經(jīng)是夠顯著的了。

    更多信息請(qǐng)查看IT技術(shù)專(zhuān)欄

    更多信息請(qǐng)查看腳本欄目
    易賢網(wǎng)手機(jī)網(wǎng)站地址:利用Psyco提升Python運(yùn)行速度
    由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢(xún)回復(fù)僅供參考,敬請(qǐng)考生以權(quán)威部門(mén)公布的正式信息和咨詢(xún)?yōu)闇?zhǔn)!

    2025國(guó)考·省考課程試聽(tīng)報(bào)名

    • 報(bào)班類(lèi)型
    • 姓名
    • 手機(jī)號(hào)
    • 驗(yàn)證碼
    關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡(jiǎn)要咨詢(xún) | 簡(jiǎn)要咨詢(xún)須知 | 新媒體/短視頻平臺(tái) | 手機(jī)站點(diǎn) | 投訴建議
    工業(yè)和信息化部備案號(hào):滇ICP備2023014141號(hào)-1 云南省教育廳備案號(hào):云教ICP備0901021 滇公網(wǎng)安備53010202001879號(hào) 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號(hào)
    云南網(wǎng)警備案專(zhuān)用圖標(biāo)
    聯(lián)系電話(huà):0871-65099533/13759567129 獲取招聘考試信息及咨詢(xún)關(guān)注公眾號(hào):hfpxwx
    咨詢(xún)QQ:1093837350(9:00—18:00)版權(quán)所有:易賢網(wǎng)
    云南網(wǎng)警報(bào)警專(zhuān)用圖標(biāo)