0
雷鋒網(wǎng) AI 科技評(píng)論按,作為目前最流行的編程語言之一,python 在人工智能相關(guān)的領(lǐng)域備受青睞。在編碼時(shí),代碼的運(yùn)行時(shí)間是我們需要考慮的重要因素之一。如何加快程序運(yùn)行的速度?這是很多開發(fā)者經(jīng)常會(huì)思考的問題。
工程師 Jim Anderson 分享了他的經(jīng)驗(yàn),他寫了一篇關(guān)于「通過并發(fā)性加快 python 程序的速度」的文章。Jim 有多年的編程經(jīng)驗(yàn),并且使用過各種編程語言。他曾做過嵌入式系統(tǒng)相關(guān)的工作,開發(fā)過分布式系統(tǒng),并且參加過許多會(huì)議。
如果你聽過很多關(guān)于 asyncio 被添加到 python 的討論,但是好奇它與其他并發(fā)方法相比怎么樣,或者你很好奇什么是并發(fā),以及它如何加速你的程序,那么你需要看下 Jim Anderson 的這篇文章,雷鋒網(wǎng)編譯整理。
在本文中,你將了解以下內(nèi)容:
什么是并發(fā)?
什么是并行?
一些 python 并發(fā)方法的比較,包括線程、異步和多進(jìn)程
在程序中何時(shí)使用并發(fā)性以及使用哪個(gè)模塊
本文假設(shè)讀者對(duì) python 有一個(gè)基本的了解,并且使用 python3.6 及以上版來運(yùn)行示例。你可以從 Real python GitHub repo 下載示例。
什么是并發(fā)?
并發(fā)這個(gè)詞在字典里面定義是「同時(shí)發(fā)生」。在 python 中,同時(shí)發(fā)生的事情由線程、任務(wù)、進(jìn)程調(diào)用,但在高層,它們都是指按順序運(yùn)行的一系列指令。
我喜歡把它們看作是不同的思維方式。它們都可以在特定的點(diǎn)上停止,此時(shí),正在處理它們的 CPU 或大腦可以切換到其它的點(diǎn)上。每件事的狀態(tài)都會(huì)被保存,這樣它就可以在中斷的地方重新啟動(dòng)。
你可能想知道為什么 python 對(duì)相同的概念使用不同的詞。事實(shí)證明,只有從宏觀意義上看線程、任務(wù)和進(jìn)程時(shí),它們才是相同的。一旦你開始深入了解細(xì)節(jié),它們都代表著一些稍微不同的東西。隨著示例的不斷深入,你將看到更多不同之處。
你必須小心謹(jǐn)慎,因?yàn)楫?dāng)你深入到細(xì)節(jié)的時(shí)候,實(shí)際上只有多進(jìn)程在同一時(shí)間運(yùn)行著多個(gè)任務(wù)。線程和異步都在單個(gè)處理器上運(yùn)行,因此一次只能處理一個(gè)任務(wù)。他們只是聰明地找到方法輪流加速整個(gè)過程。即使它們不同時(shí)運(yùn)行不同的程序,我們?nèi)匀环Q之為并發(fā)。
線程或任務(wù)輪流執(zhí)行的方式是線程和異步之間的巨大區(qū)別。在線程中,操作系統(tǒng)實(shí)際上知道每個(gè)線程,并且可以隨時(shí)中斷它以開始運(yùn)行不同的線程。這被稱為先占式多工法(pre-emptive multitasking),因?yàn)椴僮飨到y(tǒng)可以對(duì)線程進(jìn)行切換。雷鋒網(wǎng)
先占式多工法(pre-emptive multitasking)很方便,因?yàn)榫€程中的代碼不需要做任何事情來進(jìn)行切換。但它也是困難的,因?yàn)椤冈谌魏螘r(shí)候」都可能需要進(jìn)行任務(wù)切換。這種轉(zhuǎn)換可以發(fā)生在單個(gè) python 語句的中間,甚至是像 x=x+1 這樣的簡(jiǎn)單語句。
另一方面,asyncio 使用協(xié)同多任務(wù)處理。這些任務(wù)必須通過宣布它們何時(shí)準(zhǔn)備好被關(guān)閉來協(xié)同合作。這意味著要實(shí)現(xiàn)這一點(diǎn),任務(wù)中的代碼必須稍微更改才能實(shí)現(xiàn)這一點(diǎn)。
提前做這些額外的工作的好處是,你總是知道你的任務(wù)將在哪里被切換。除非該語句被標(biāo)記,否則任務(wù)不會(huì)在 python 語句的中間被切換。接下來你將看到如何簡(jiǎn)化設(shè)計(jì)的各個(gè)部分。
什么是并行?
到目前為止,你已經(jīng)研究了在單個(gè)處理器上發(fā)生的并發(fā)。那么對(duì)于你的新筆記本電腦上的那么多 CPU 核會(huì)怎么樣呢?你如何利用它們?答案就是多進(jìn)程。
通過多進(jìn)程,python 創(chuàng)建了新的進(jìn)程。這里的一個(gè)進(jìn)程可以被看作是一個(gè)完全不同的程序,盡管從技術(shù)上講,它們通常被定義為一個(gè)資源的集合,其中的資源包括內(nèi)存、文件句柄和類似的東西。每個(gè)進(jìn)程都在自己的 python 解釋器中運(yùn)行。
因?yàn)樗鼈兪遣煌倪M(jìn)程,所以在多進(jìn)程中的每一個(gè)進(jìn)程都可以在不同的核上運(yùn)行。在不同的核心上運(yùn)行意味著它們實(shí)際上可以同時(shí)運(yùn)行,這太棒了。這樣做會(huì)產(chǎn)生一些復(fù)雜的情況,但是在大多數(shù)情況下,python 都能很好地平衡它們。
并發(fā)何時(shí)有用?
并發(fā)性可以對(duì)兩種類型的問題產(chǎn)生很大的影響。這通常稱為 CPU 綁定和 I/O 綁定。
I/O 綁定問題會(huì)導(dǎo)致程序運(yùn)行速度減慢,因?yàn)樗3P枰却齺碜阅承┩獠抠Y源的輸入/輸出(I/O)。當(dāng)你的程序處理比你的 CPU 慢得多的東西時(shí),這種情況經(jīng)常發(fā)生。
比你的 CPU 慢的事情很多,但謝天謝地,它們中間的大多數(shù)都不會(huì)與你的程序有關(guān)聯(lián)。你的程序最常與之交互的緩慢的事情是文件系統(tǒng)和網(wǎng)絡(luò)連接。
讓我們看看它們是什么樣子的:
在上面的示意圖中,藍(lán)色框顯示程序工作的時(shí)間,紅色框顯示等待 I/O 操作完成的時(shí)間。這個(gè)圖并不是按比例繪制的,因?yàn)?Internet 上的請(qǐng)求時(shí)間可能比 CPU 指令長(zhǎng)幾個(gè)數(shù)量級(jí),所以你的程序最終可能會(huì)花費(fèi)大部分時(shí)間等待操作完成。這是你的瀏覽器在大多數(shù)時(shí)間里所做的事情。
另一方面,有一些程序可以在不與網(wǎng)絡(luò)通信或不訪問文件的情況下進(jìn)行重要的計(jì)算。這些是 CPU 綁定的程序,因?yàn)橄拗瞥绦蛩俣鹊馁Y源是 CPU,而不是網(wǎng)絡(luò)或文件系統(tǒng)。
以下是 CPU 綁定程序的示意圖:
當(dāng)你完成下面部分中的示例時(shí),你將看到不同形式的并發(fā)在 CPU 綁定的程序和 I/O 綁定的程序中工作得更好或更差。向程序添加并發(fā)性會(huì)增加額外的代碼,增大復(fù)雜性,因此你需要確定潛在的加速是否值得付出這些代價(jià)??赐瓯疚?,你應(yīng)該有足夠的信息來開始做這個(gè)決定。
關(guān)于概念的介紹就到這里啦,下面的文章中,你將看到 I/O 綁定程序相關(guān)的內(nèi)容,之后,你將看到一些處理 CPU 綁定程序的代碼。
接下來的部分請(qǐng)查看:
如何利用并發(fā)性加速你的python程序(二):I/O 綁定程序加速
如何利用并發(fā)性加速你的python程序(三):CPU 綁定程序加速
via:http://www.ozgbdpf.cn/news/201901/JfoLltRClm3bZzuB.html?type=preview
雷峰網(wǎng)版權(quán)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。