1. 程式人生 > >2018年5月19日筆記

2018年5月19日筆記

共享內存 main 多核cpu 需要 target 創建 uil out lease

  • 進程的概念

進程是程序在計算機上的一次執行活動。

進程可分為系統進程和用戶進程。

所有正在運行的進程輪流使用CPU,任何一個時間點有且只有一個進程占用CPU。

  • 進程與線程的區別

進程 > 線程

多進程使用CPU的多個核,適合運算密集型

多線程使用CPU的一個核,核心IO密集型

  • python多進程 —— muiltiprocessing模塊

python中的多線程無法利用多核優勢,如果想要充分地使用多核CPU的資源(os.cpu_count()查看),在python中大部分情況需要使用多進程。Python提供了multiprocessing。

Multiprocessing支持子進程、通信和共享數據、執行不同形式的同步,提供了Process、Queue、Pipe、Lock等組件。

  • 創建一個Process實例
p1 = multiprocessing.Process(target=func, args=(2,))

target=函數名字

args=函數所需的參數,以tuple形式傳入,必須有逗號,註意單個參數的形式

multiprocessing的2個常用方法:

multiprocessing.cpu_count()     # 1. 統計CPU總數

multiprocessing.active_children()       # 2. 獲取所有子進程

  • Process實例的常用屬性和方法

常用屬性:

p1 = multiprocessing.Process(target=func, args=(2,))
p1.name     
# 進程名字 p1.pid # 進程ID

常用方法:

p1 = multiprocessing.Process(target=func, args=(2,))
p1.is_alive()       # 判斷進程是否存活
p1.run()            # 啟動進程(不常用)
p1.start()          # 啟動進程,自動調用run()方法(常用)
p1.join(timeout=5)  # 等待進程結束或直到超時(5s)

  • 習題1
 1 import multiprocessing
 2 import time
 3 
 4 
 5 def
worker(args, interval): 6 print("start worker {0}".format(args)) 7 time.sleep(interval) 8 print("end worker {0}".format(args)) 9 10 def main(): 11 print("start main") 12 p1 = multiprocessing.Process(target=worker, args=(1, 1)) 13 p2 = multiprocessing.Process(target=worker, args=(2, 2)) 14 p3 = multiprocessing.Process(target=worker, args=(3, 3)) 15 p1.start() 16 p2.start() 17 p3.start() 18 print("end main") 19 20 if __name__ == __main__: 21 main()
start main
end main
start worker 1
start worker 2
start worker 3
end worker 1
end worker 2
end worker 3

  • 習題2
 1 import multiprocessing
 2 import time
 3 
 4 def worker(args, interval):
 5     print("start worker {0}".format(args))
 6     time.sleep(interval)
 7     print("end worker {0}".format(args))
 8 
 9 def main():
10     print("start main")
11     p1 = multiprocessing.Process(target=worker, args=(1, 1))
12     p2 = multiprocessing.Process(target=worker, args=(2, 2))
13     p3 = multiprocessing.Process(target=worker, args=(3, 3))
14     p1.start()
15     p1.join(timeout=0.5)
16     p2.start()
17     p3.start()
18     print("the number of CPU is: {0}".format(multiprocessing.cpu_count()))
19     for p in multiprocessing.active_children():
20        print("The name of active children is: {0}, pid is: {1} is alive".format(p.name, p.pid))
21     print("end main")
22 
23 if __name__ == __main__:
24     main()
start main
start worker 1
the number of CPU is: 4
The name of active children is: Process-1, pid is: 1348 is alive
The name of active children is: Process-3, pid is: 1350 is alive
The name of active children is: Process-2, pid is: 1349 is alive
end main
start worker 2
start worker 3
end worker 1
end worker 2
end worker 3

  • Lock組件

使用多進程來讀寫文件時,讀和寫不能同時進行,為了這種多個進程共享同一資源的場景不出問題,引入了鎖機制。

鎖有兩種狀態:被鎖(locked)和沒有被鎖(unlocked)。擁有acquire()和release()兩種方法,並且遵循一下的規則:

  • 如果一個鎖的狀態是unlocked,調用acquire()方法改變它的狀態為locked
  • 如果一個鎖的狀態是locked,acquire()方法將會阻塞,直到另一個線程調用release()方法釋放了鎖;
  • 如果一個鎖的狀態是unlocked調用release()會拋出RuntimeError異常;
  • 如果一個鎖的狀態是locked,調用release()方法改變它的狀態為unlocked。

  • 習題3
 1 import multiprocessing
 2 import time
 3 
 4 def add1(lock, value, number):
 5     with lock:
 6         print("start add1 number= {0}".format(number))
 7         for i in range(1, 5):
 8             number += value
 9             time.sleep(0.3)
10             print("number = {0}".format(number))
11 
12 def add3(lock, value, number):
13     lock.acquire()
14     print("start add3 number= {0}".format(number))
15     try:
16         for i in range(1, 5):
17             number += value
18             time.sleep(0.3)
19             print("number = {0}".format(number))
20     except Exception as e:
21         raise e
22     finally:
23         lock.release()
24         pass
25 
26 if __name__ == __main__:
27     print("start main")
28     number = 0
29     lock = multiprocessing.Lock()
30     p1 = multiprocessing.Process(target=add1, args=(lock, 1, number))
31     p3 = multiprocessing.Process(target=add3, args=(lock, 3, number))
32     p1.start()
33     p3.start()
34     print("end main")
start main
end main
start add1 number= 0
number = 1
number = 2
number = 3
number = 4
start add3 number= 0
number = 3
number = 6
number = 9
number = 12

  • 多進程間可共享內存

multiprocessing模塊提供了共享內存的操作。

一般的變量在進程之間是無法通信的,multiprocessing提供了Value和Array模塊,實現了進程間的數據共享。

Python中還提供了強大的Manager模塊專門來做數據共享,其支持的類型非常多,包括Value, Array, list, dict, Queue, Lock等。

  • 習題4
 1 import multiprocessing
 2 from multiprocessing import Value, Array, Manager
 3 import time
 4 
 5 
 6 def add1(value, number):
 7     print("start add1 number= {0}".format(number.value))
 8     for i in range(1, 5):
 9         number.value += value
10         print("number = {0}".format(number.value))
11 
12 def add3(value, number):
13     print("start add3 number= {0}".format(number.value))
14     try:
15         for i in range(1, 5):
16             number.value += value
17             print("number = {0}".format(number.value))
18     except Exception as e:
19         raise e
20 
21 if __name__ == __main__:
22     print("start main")
23     number = Value(d, 0)
24     p1 = multiprocessing.Process(target=add1, args=(1, number))
25     p3 = multiprocessing.Process(target=add3, args=(3, number))
26     p1.start()
27     p3.start()
28     print("end main")
start main
end main
start add1 number= 0.0
number = 1.0
number = 2.0
number = 3.0
number = 4.0
start add3 number= 4.0
number = 7.0
number = 10.0
number = 13.0
number = 16.0

2018年5月19日筆記