Python 多處理器

在本章中,我們將更多地關(guān)注多處理和多線程之間的比較。

多cpu

它是在單個計算機(jī)系統(tǒng)中使用兩個或更多cpu單元。通過利用我們計算機(jī)系統(tǒng)中可用的全部cpu內(nèi)核,這是從硬件中充分發(fā)揮潛力的最佳方法。

多線程

通過并發(fā)執(zhí)行多個線程,cpu能夠管理操作系統(tǒng)的使用。多線程的主要思想是通過將進(jìn)程劃分為多個線程來實現(xiàn)并行性。

下表顯示了它們之間的一些重要差異

sr.no. multiprocessing multiprogrammingv
1 多處理是指多個cpu同時處理多個進(jìn)程。 多道程序同時在主存儲器中保存多個程序,并使用單個cpu同時執(zhí)行它們。
2 它使用多個cpu。 它使用單cpu。
3 它允許并行處理。 進(jìn)行上下文切換。
4 減少處理工作所需的時間。 處理工作所需的時間更多。
它有助于高效利用計算機(jī)系統(tǒng)的設(shè)備。 比多處理效率低。
6 通常更貴。 這種系統(tǒng)較便宜。

 

消除全球翻譯鎖(gil)的影響

在使用并發(fā)應(yīng)用程序時,python中存在一個名為 gil(全局解釋器鎖)的限制 。gil從不允許我們使用多個cpu內(nèi)核,因此我們可以說python中沒有真正的線程。gil是互斥鎖 - 互斥鎖,它使線程安全。換句話說,我們可以說gil阻止多個線程并行執(zhí)行python代碼。鎖一次只能由一個線程保存,如果我們想要執(zhí)行一個線程,那么它必須首先獲取鎖。

通過使用多處理,我們可以有效地繞過gil引起的限制 -

  • 通過使用多處理,我們正在利用多個流程的能力,因此我們正在利用gil的多個實例。

  • 因此,在任何時候都沒有限制在我們的程序中執(zhí)行一個線程的字節(jié)碼。

 

在python中啟動進(jìn)程

以下三種方法可用于在多處理模塊中以python啟動進(jìn)程 -

  • fork
  • spawn
  • forkserver

使用fork創(chuàng)建進(jìn)程

fork命令是unix中的標(biāo)準(zhǔn)命令。它用于創(chuàng)建稱為子進(jìn)程的新進(jìn)程。此子進(jìn)程與稱為父進(jìn)程的進(jìn)程同時運(yùn)行。這些子進(jìn)程也與其父進(jìn)程相同,并繼承了父進(jìn)程可用的所有資源。使用fork創(chuàng)建進(jìn)程時使用以下系統(tǒng)調(diào)用

  • fork() - 這是一個通常在內(nèi)核中實現(xiàn)的系統(tǒng)調(diào)用。 它用于創(chuàng)建process.p>的副本

  • getpid() - 此系統(tǒng)調(diào)用返回調(diào)用進(jìn)程的進(jìn)程id(pid)。

以下python腳本示例將幫助您了解如何創(chuàng)建新的子進(jìn)程并獲取子進(jìn)程和父進(jìn)程的pid -

import os

def child():
   n = os.fork()

   if n > 0:
      print("pid of parent process is : ", os.getpid())

   else:
      print("pid of child process is : ", os.getpid())
child()

產(chǎn)量

pid of parent process is : 25989
pid of child process is : 25990

 

使用spawn創(chuàng)建進(jìn)程

spawn意味著開始新事物。因此,產(chǎn)生進(jìn)程意味著父進(jìn)程創(chuàng)建新進(jìn)程。父進(jìn)程以異步方式繼續(xù)執(zhí)行,或等待子進(jìn)程結(jié)束執(zhí)行。按照以下步驟生成流程 -

  • 導(dǎo)入多處理模塊。

  • 創(chuàng)建對象流程。

  • 通過調(diào)用 start() 方法啟動進(jìn)程活動。

  • 等待進(jìn)程完成其工作并通過調(diào)用 join() 方法退出。

以下python腳本示例有助于生成三個進(jìn)程

import multiprocessing

def spawn_process(i):
   print ('this is process: %s' %i)
   return

if __name__ == '__main__':
   process_jobs = []
   for i in range(3):
   p = multiprocessing.process(target = spawn_process, args = (i,))
      process_jobs.append(p)
   p.start()
   p.join()

輸出

this is process: 0
this is process: 1
this is process: 2

 

使用forkserver創(chuàng)建進(jìn)程

forkserver機(jī)制僅適用于那些支持通過unix管道傳遞文件描述符的所選unix平臺??紤]以下幾點來理解forkserver機(jī)制的工作原理 -

  • 使用forkserver機(jī)制實例化服務(wù)器以啟動新進(jìn)程。

  • 然后,服務(wù)器接收命令并處理創(chuàng)建新進(jìn)程的所有請求。

  • 為了創(chuàng)建一個新進(jìn)程,我們的python程序?qū)⑾騠orkserver發(fā)送一個請求,它將為我們創(chuàng)建一個進(jìn)程。

  • 最后,我們可以在我們的程序中使用這個新創(chuàng)建的過程。

 

守護(hù)程序在python中處理

python 多處理 模塊允許我們通過其守護(hù)進(jìn)程選項獲得守護(hù)進(jìn)程。守護(hù)程序進(jìn)程或在后臺運(yùn)行的進(jìn)程遵循與守護(hù)程序線程類似的概念。要在后臺執(zhí)行該過程,我們需要將守護(hù)程序標(biāo)志設(shè)置為true。只要主進(jìn)程正在執(zhí)行,守護(hù)程序進(jìn)程將繼續(xù)運(yùn)行,并且它將在完成執(zhí)行后或主程序被終止時終止。

在這里,我們使用與守護(hù)程序線程中使用的相同的示例。唯一的區(qū)別是模塊從變化 多線程 來 多 和惡魔的標(biāo)志設(shè)置為true。但是,輸出會有變化,如下所示

import multiprocessing
import time

def nondaemonprocess():
   print("starting my process")
   time.sleep(8)
   print("ending my process")
def daemonprocess():
   while true:
   print("hello")
   time.sleep(2)
if __name__ == '__main__':
   nondaemonprocess = multiprocessing.process(target = nondaemonprocess)
   daemonprocess = multiprocessing.process(target = daemonprocess)
   daemonprocess.daemon = true
   nondaemonprocess.daemon = false
   daemonprocess.start()
   nondaemonprocess.start()

輸出

starting my process
ending my process

與守護(hù)程序線程生成的輸出相比,輸出是不同的,因為沒有守護(hù)程序模式的進(jìn)程具有輸出。因此,守護(hù)進(jìn)程在主程序結(jié)束后自動結(jié)束,以避免運(yùn)行進(jìn)程的持久性。

 

在python中終止進(jìn)程

我們可以使用 terminate() 方法立即終止或終止進(jìn)程。我們將在完成執(zhí)行之前立即使用此方法終止在函數(shù)幫助下創(chuàng)建的子進(jìn)程。

import multiprocessing
import time
def child_process():
   print ('starting function')
   time.sleep(5)
   print ('finished function')
p = multiprocessing.process(target = child_process)
p.start()
print("my process has terminated, terminating main thread")
print("terminating child process")
p.terminate()
print("child process successfully terminated")

輸出

my process has terminated, terminating main thread
terminating child process
child process successfully terminated

輸出顯示程序在執(zhí)行子進(jìn)程之前終止,該子進(jìn)程是在child_process()函數(shù)的幫助下創(chuàng)建的。這意味著子進(jìn)程已成功終止。

 

在python中識別當(dāng)前進(jìn)程

操作系統(tǒng)中的每個進(jìn)程都具有稱為pid的進(jìn)程標(biāo)識。在python中,我們可以借助以下命令找出當(dāng)前進(jìn)程的pid

import multiprocessing
print(multiprocessing.current_process().pid)

下面的python腳本示例有助于找出主進(jìn)程的pid以及子進(jìn)程的pid

import multiprocessing
import time
def child_process():
   print("pid of child process is: {}".format(multiprocessing.current_process().pid))
print("pid of main process is: {}".format(multiprocessing.current_process().pid))
p = multiprocessing.process(target=child_process)
p.start()
p.join()

輸出

pid of main process is: 9401
pid of child process is: 9402

 

在子類中使用進(jìn)程

我們可以通過對 threading.thread 類進(jìn)行子類化來創(chuàng)建線程。此外,我們還可以通過對 multiprocessing.process 類進(jìn)行子類化來創(chuàng)建進(jìn)程。對于在子類中使用進(jìn)程,我們需要考慮以下幾點 -

  • 我們需要定義 process 類的新子類。

  • 我們需要覆蓋 init(self [,args]) 類。

  • 我們需要覆蓋 run(self [,args]) 方法來實現(xiàn)什么 process

  • 我們需要通過調(diào)用 start() 方法來啟動該過程。

import multiprocessing
class myprocess(multiprocessing.process):
   def run(self):
   print ('called run method in process: %s' %self.name)
   return
if __name__ == '__main__':
   jobs = []
   for i in range(5):
   p = myprocess()
   jobs.append(p)
   p.start()
   p.join()

輸出

called run method in process: myprocess-1
called run method in process: myprocess-2
called run method in process: myprocess-3
called run method in process: myprocess-4
called run method in process: myprocess-5

 

python多處理模塊 - 池類

如果我們在python應(yīng)用程序中討論簡單的并行 處理 任務(wù),那么多處理模塊為我們提供了pool類。 pool 類的以下方法可用于在主程序中啟動子進(jìn)程的數(shù)量

apply()方法

此方法類似于 .threadpoolexecutor的.submit() 方法 。 它會阻塞,直到結(jié)果準(zhǔn)備就緒。

apply_async()方法

當(dāng)我們需要并行執(zhí)行任務(wù)時,我們需要使用 apply_async() 方法將任務(wù)提交到池中。它是一個異步操作,在執(zhí)行所有子進(jìn)程之前不會鎖定主線程。

map()方法

就像 apply() 方法一樣,它也會阻塞,直到結(jié)果準(zhǔn)備好。它等同于內(nèi)置的 map() 函數(shù),該函數(shù)將可迭代數(shù)據(jù)拆分為多個塊,并作為單獨的任務(wù)提交給進(jìn)程池。

map_async()方法

它是 map() 方法的變體,因為 apply_async() 是 apply() 方法。它返回一個結(jié)果對象。結(jié)果準(zhǔn)備就緒后,將對其應(yīng)用可調(diào)用對象。必須立即完成贖回; 否則,處理結(jié)果的線程將被阻止。

以下示例將幫助您實現(xiàn)用于執(zhí)行并行執(zhí)行的進(jìn)程池。通過 multiprocessing.pool 方法應(yīng)用 square() 函數(shù),已經(jīng)執(zhí)行了簡單的數(shù)字 平方 計算。然后 pool.map() 用于提交5,因為input是0到4之間的整數(shù)列表。結(jié)果將存儲在 p_outputs中 并打印出來。

def square (n):
   result = n*n
   return result
if __name__ == '__main__':
   inputs = list(range(5))
   p = multiprocessing.pool(processes = 4)
   p_outputs = pool.map(function_square, inputs)
   p.close()
   p.join()
   print ('pool :', p_outputs)

輸出

pool : [0, 1, 4, 9, 16]

下一節(jié):python 處理器通信

相關(guān)文章
亚洲国产精品第一区二区,久久免费视频77,99V久久综合狠狠综合久久,国产免费久久九九免费视频