1. 程式人生 > >Python 多程序 multiprocessing 上篇

Python 多程序 multiprocessing 上篇

'''
Python由於全域性直譯器鎖(GIL)的存在,多執行緒並不能發揮多核的效能。
實際上,即使使用多執行緒,每時刻執行的只是一個執行緒,因為只有執行緒獲得GIL鎖才可以執行。
在某一執行緒執行100條位元組碼或者進入IO操作的時候,會釋放GIL,切入另一個執行緒。

因此,為了發揮多核的效能,我們使用多程序的方式,Pythond的標準庫中,有跨平臺的
多程序模組multiprocessing。
下面介紹,multiprocessing的使用
'''
import os, time
import multiprocessing 

'''
multiprocessing中的Process類用來建立程序物件,需要指定執行的函式,
函式的輸入值, Process(target = func_name, args = input_args)
args要使用元組的形式,即使有一個引數a,也要寫成args = (a, )的形式。
下面是建立兩個程序的例子
''' # 例子1 def job01(n): print("Current Process is at PID({}), input is {}.".format(os.getpid(), n)) # os.getpid()獲得當前執行的程序的程序號PID x = 0 for i in range(n): x += i**3 print("Result is {}.".format(x)) return x def main01(): p1 = multiprocessing.Process(target = job01, args = (10, )) p2
= multiprocessing.Process(target = job01, args = (110, )) p1.start() p2.start() # 如果執行這個例子,取消下面註釋 ''' if __name__ == "__main__": main01() ''' # join的作用 ''' 當p1, p2 start之後,總共有3個程序,p1, p2和主程序 如果p2.start()語句之後還有一句,print("All done.") 看例子2 其中,為了更明顯看出問題,使得job執行時間更長,添加了一句 time.sleep(10) #當前程序所在的核,停止10秒 例子2的執行結果如下, All done. Current Process is at PID(10756), input is 110. Current Process is at PID(6224), input is 10. Result is 35940025. Result is 2025. 很奇怪,為什麼,先輸出了"All done." 明明把print("All done.")放在了p1.start(),p2.start()後面。 因為,start只是開始啟動程序,一旦啟動,就繼續執行後面的語句了, 不在理會p1和p2是在幹什麼,由於p1和p2執行時間長, 所以,print("All done.")之後才執行完p1,p2 但是這和程式邏輯不符。 所以,在要在p1.start()後面加上一句 p1.join() 表示只有p1執行結束,才會繼續執行主程序後面的語句。 修改後,參看例子3
''' # 例子2 def job02(n): print("Current Process is at PID({}), input is {}.".format(os.getpid(), n)) # os.getpid()獲得當前執行的程序的程序號PID time.sleep(10) x = 0 for i in range(n): x += i**3 print("Result is {}.".format(x)) return x def main02(): p1 = multiprocessing.Process(target = job01, args = (10, )) p2 = multiprocessing.Process(target = job01, args = (110, )) p1.start() p2.start() print("All done.") # 如果執行這個例子,取消下面註釋 ''' if __name__ == "__main__": main02() ''' # 例子3 def main03(): p1 = multiprocessing.Process(target = job01, args = (10, )) p2 = multiprocessing.Process(target = job01, args = (110, )) p1.start() p1.join() p2.start() p2.join() print("All done.") # 如果執行這個例子,取消下面註釋 ''' if __name__ == "__main__": main03() ''' ''' 例子3執行結果如下: Current Process is at PID(500), input is 10. Result is 2025. Current Process is at PID(14064), input is 110. Result is 35940025. All done. 和我們的邏輯一樣。 All done. 在最後輸出。 '''
# 程序池 Pool 的使用
'''
每次用一個Process有些麻煩,當我們需要多個程序,只是輸入不同,有沒有簡單的方法呢。
答案使用Pool,例子4
'''

import os, time 
import multiprocessing
from multiprocessing import Process, Pool 

def job01(n):
    print("Current Process is {} at PID({})."
        .format(multiprocessing.current_process().name, os.getpid()))
    x = 0
    for i in range(n):
        x += i**4 
    print("Result: {}".format(x))
    if n == 3:
        time.sleep(5)
    return x

def main():
    print(multiprocessing.current_process().name)
    nums = [1, 3, 8, 110]
    pool = Pool(processes = 3)
    print(pool.map(job01, nums))

if __name__ == "__main__":
    main()

'''
multiprocessing.current_process().name
獲得當前程序的名稱
實際上,設定一個程序的時候,是可以指定名稱的。比如,
p = Process(target = job, args = input, name = "Hello")
主程序的名字是 "MainProcess"

Pool(processes = 4)設定程序的數目
預設是機器的邏輯處理器數目,8核16執行緒的cpu,預設是16。
可以,通過multiprocessing.cpu_count()得到這個數目

如果,我設定為3會怎麼樣?
有4個輸入!
會只有三個程序,只有一個程序結束後,才會輸入第4個數,開啟新的程序。
但是,同時最多3個程序。

這裡,我故意將n=3的情況,sleep(5)使他的執行時間最長,
但是我們發現,輸出還是按照輸入的順序。

'''
#