69pao国产精品视频-久久精品一区二区二三区-精品国产精品亚洲一本大道-99国产综合一区久久

Python 多處理器

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

多cpu

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

多線程

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

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

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

 

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

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

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

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

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

 

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

以下三種方法可用于在多處理模塊中以python啟動(dòng)進(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)程同時(shí)運(yùn)行。這些子進(jìn)程也與其父進(jìn)程相同,并繼承了父進(jìn)程可用的所有資源。使用fork創(chuàng)建進(jìn)程時(shí)使用以下系統(tǒng)調(diào)用

  • fork() - 這是一個(gè)通常在內(nèi)核中實(shí)現(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)建對(duì)象流程。

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

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

以下python腳本示例有助于生成三個(gè)進(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平臺(tái)??紤]以下幾點(diǎn)來理解forkserver機(jī)制的工作原理 -

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

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

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

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

 

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

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

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

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ù)程序線程生成的輸出相比,輸出是不同的,因?yàn)闆]有守護(hù)程序模式的進(jìn)程具有輸出。因此,守護(hù)進(jìn)程在主程序結(jié)束后自動(dòng)結(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中識(shí)別當(dāng)前進(jìn)程

操作系統(tǒng)中的每個(gè)進(jìn)程都具有稱為pid的進(jìn)程標(biāo)識(shí)。在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)程

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

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

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

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

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

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多處理模塊 - 池類

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

apply()方法

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

apply_async()方法

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

map()方法

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

map_async()方法

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

以下示例將幫助您實(shí)現(xiàn)用于執(zhí)行并行執(zhí)行的進(jìn)程池。通過 multiprocessing.pool 方法應(yīng)用 square() 函數(shù),已經(jīng)執(zhí)行了簡單的數(shù)字 平方 計(jì)算。然后 pool.map() 用于提交5,因?yàn)閕nput是0到4之間的整數(shù)列表。結(jié)果將存儲(chǔ)在 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)文章