1. 程式人生 > >『Python』多進程處理

『Python』多進程處理

rgs map multicore 變量 實例化 read reat 嘗試 學習

嘗試學習python的多進程模組,對比多線程,大概的區別在:

  1.多進程的處理速度更快

  2.多進程的各個子進程之間交換數據很不方便

多進程調用方式

  進程基本使用multicore()

  進程池優化進程的調用multicore_pool(),在使用進程池的時候,運許函數有return,而基本用法中進程是接收不了return的

  進程隊列用法,大部分方法和python的基本隊列是一致的,

q=mp.Queue() 聲明
q.put() 添加
q.get() 釋放
q.empty() 判斷是不是空的
"""
Created on Tue Dec  5 09:00:00 2017

@author: hellcat
"""

import time
import numpy as np
import threading as td
import multiprocessing as mp

def job(q):
    for i in range(3):
        q.put(i)
    
def multicore():
    q=mp.Queue()
    ps = [mp.Process(target=job,args=(q,)),
         mp.Process(target=job,args=(q,))]  # 基本的子進程創建方法
    for p in ps:
        p.start()
        
    time.sleep(3)
    
    for p in ps:
        p.join()                            # 需要協調結束
        
    while True:
        if q.empty() != True:
            print(q.get())
        else:
            break

def multithread():  
    q=mp.Queue()
    ps = [td.Thread(target=job,args=(q,)),
         td.Thread(target=job,args=(q,))]  # 基本的子線程創建方法
    for p in ps:
        p.start()
        
    time.sleep(3)
    
    for p in ps:
        p.join()
        
    while True:
        if q.empty() != True:
            print(q.get())
        else:
            break

def job_pool(q):
    res0 = 0
    for i in range(np.random.randint(10)):
        res0 += i**3
    return res0

def multicore_pool():
    pool = mp.Pool(processes=2)                                  # 初始化進程池,可以指定進程數
    res1 = pool.map(job_pool,range(20))                          # map方法在線程池中同時添加多個線程
    print(res1)                              # 返回值為函數的return
    res2 = [pool.apply_async(job_pool,(i,)) for i in range(20)]  # 在進程池中單個添加進程
    print([res.get() for res in res2])                           # 註意此時每個進程的返回並不直接是return,需要get方法得到的才是return
    # for res in res2:
    #     print(res.get())
    
if __name__==‘__main__‘:
    # multicore()
    # multithread()
    multicore_pool()

進程共享變量 & 進程鎖

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Dec  5 10:15:58 2017

@author: hellcat
"""

import time
import multiprocessing as mp

def job(v,num,l):  # 需要把共享變量實例作為參數傳入才行
    l.acquire()  # 進程鎖鎖住
    for _ in range(10):
        time.sleep(0.1)
        v.value += num # 獲取共享變量的值,並進行操作
        print(v.value)
    l.release()  # 進程鎖釋放

def muticore():
    l = mp.Lock()  # 實例化進程鎖
    v = mp.Value(‘i‘,0)  # 實例化共享變量
    # p = mp.Pool(processes=2)
    
    # p.map(job,((v,1,l),(v,3,l)))
    p1 = mp.Process(target=job,args=(v,1,l))
    p2 = mp.Process(target=job,args=(v,3,l))
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    
if __name__==‘__main__‘:
    muticore()

  不同於多線程使用全局變量就可以以共享變量,多進程必須使用 v = mp.Value(‘i‘,0)這樣的語句聲明變量(其實還可以是mp.Array(‘i‘,[1,2,3]),註意,這裏只能是1維的list,[[1,2]]這樣都是不可以的),並將v作為參數傳給函數,在函數內部使用的時候也需要使用v.value來喚醒其值。

  進程鎖會在鎖住時阻止其他進程使用共享變量,所以可以看到輸出中先執行了10次+1,然後執行了10次+3,而不使用進程鎖+1和+3會無規律的交替進行:

註釋掉進程鎖:

1
4
5
8
9
12
13
16
17
20
21
24
25
28
29
32
33
36
37
40

使用進程鎖(上面代碼沒有註釋掉進程鎖):

1
2
3
4
5
6
7
8
9
10
13
16
19
22
25
28
31
34
37
40

『Python』多進程處理