一篇文章学习Python中的多进程

一、什么是多进程 Multiprocessing

支持并行运算,充分利用计算机的多核CPU

二、添加多进程 Process

import multiprocessing as mp

def process_job(a,b):
    print("a:",a)
    print("b:",b)

if __name__=="__main__":
    p1 = mp.Process(target=process_job,args=(1,2))  # 定义一个进程p1
    p1.start()                                      # 开启进程p1
    p1.join()                                       # 将进程p1加入到主进程

三、存储进程输出 Queue

多进程调用的函数不能有返回值,故使用Queue存储结果。

import multiprocessing as mp

def process_job(q):
    res = 0
    for i in range(10):
        res += i
    q.put(res)
        
if __name__=="__main__":
    q = mp.Queue()
    p1 = mp.Process(target=process_job,args=(q,))  # 注意args必须是可迭代的类型,但只有一个参数的时候,要加一个逗号
    p2 = mp.Process(target=process_job,args=(q,))
    p1.start()
    p2.start()
    p2.join()
    p1.join()

    print("res1:",q.get())
    print("res2:",q.get())

四、效率对比 threading & multiprocessing

import multiprocessing as mp
import threading as td
import time

def job(q):
    res = 0
    for i in range(100000):
        res += i + i**2 + i**3
    q.put(res)

def multiProcess():    # 多进程运算
    q = mp.Queue()
    p1 = mp.Process(target=job,args=(q,))  
    p2 = mp.Process(target=job,args=(q,))  
    p1.start()
    p2.start()
    p2.join()
    p1.join()
    print("multiProcess_res:",q.get()+q.get())

def multiThread():    # 多线程运算
    q = mp.Queue()
    t1 = td.Thread(target=job,args=(q,))
    t2 = td.Thread(target=job,args=(q,))
    t1.start()
    t2.start()
    t2.join()
    t1.join()
    print("numliThread_res:",q.get()+q.get())

def normal():         # 普通运算
    res = 0
    for _ in range(2):
        for i in range(100000):
            res += i + i**2 + i**3
    print("normal_res:",res)

if __name__=="__main__":
    t1 = time.time()
    normal()
    t2 = time.time()
    print("normal_time:",t2-t1)
    multiProcess()
    t3 = time.time()
    print("multiProcess_time:",t3-t2)
    multiThread()
    t4 = time.time()
    print("multiThread_time:",t4-t3)

结果:运行时间 多进程 < 多线程 (多线程和普通的运行时间差不多)

normal_res: 49999666671666600000
normal_time: 0.2157750129699707
multiProcess_res: 49999666671666600000
multiProcess_time: 0.14542102813720703
numliThread_res: 49999666671666600000
multiThread_time: 0.2052018642425537

五、进程池 Pool

相当于批量处理多进程
与 Process 不同的是,Pool 有返回值,返回值是一个 list,依次是每个进程执行的结果。

import multiprocessing as mp

def job(x):
    return x*x
    
def multicore():
    pool = mp.Pool(processes=2)       
    res = pool.map(job, range(10))     # 方式一:使用 pool 的 map 函数
    print(res)
    
    res = pool.apply_async(job, (2,))
    print(res.get())
    
    multi_res =[pool.apply_async(job, (i,)) for i in range(10)]   #方式二:使用 pool 的 apply_async 函数
    print([res.get() for res in multi_res])
    
if __name__ == '__main__':
    multicore()

六、共享内存 shared memory

在上一篇文章的第六部分线程锁可以看到,对于一个全局变量,多个线程之间共享全局变量,一个线程对全局变量修改以后,其他线程访问到的是修改后的全局变量,会造成数据的混乱。
与多线程不同的是,多进程不会共享全局变量,多个进程之间不进行交流,任意一个进程对全局变量的修改都不会影响到其他进程对全局变量的访问。
比如:

import multiprocessing as mp

def job1():
    global A
    for i in range(3):
        A += 1
        print("Job1:",A)
def job2():
    global A
    for i in range(3):
        A += 10
        print("Job2:",A)
        
if __name__=="__main__":
    A = 0
    p1 = mp.Process(target=job1)
    p2 = mp.Process(target=job2)
    p1.start()
    p2.start()
    p2.join()
    p1.join()

结果:互不影响

1
2
10
3
20
30

因此,需要设置共享内存,让进程之间进行交流:
1、Shared Value
通过使用 Value 将数据存储在一个共享的内存表中

import multiprocessing as mp

value1 = mp.Value('i', 0) 
value2 = mp.Value('d', 3.14)

其中 d 和 i 参数用来设置数据类型的,d 表示一个双精浮点类型,I 表示一个带符号的整型。
2、Shared Array
mutiprocessing中,有还有一个Array类,可以和共享内存交互,来实现在进程之间共享数据

array = mp.Array('i', [1, 2, 3, 4])

这里的Array和numpy中的不同,它只能是一维的,不能是多维的。同样和Value 一样,需要定义数据形式,否则会报错。
参数数据类型表

七、进程锁 Lock

1、不加进程锁

import multiprocessing as mp
import time

def job(v, num):
    for _ in range(5):
        time.sleep(0.1) # 暂停0.1秒,让输出效果更明显
        v.value += num # v.value获取共享变量值
        print(v.value, end="")
                
def multicore():
    v = mp.Value('i', 0) # 定义共享变量
    p1 = mp.Process(target=job, args=(v,1))
    p2 = mp.Process(target=job, args=(v,3)) # 设定不同的number看如何抢夺内存
    p1.start()
    p2.start()
    p1.join()
    p2.join()    
    
if __name__ == '__main__':
    multicore()

结果:进程1和进程2在相互抢着使用共享内存v

1
4
5
8
9
12
13
16
17
20

2、加进程锁

import multiprocessing as mp
import time

def job(v, num, l):
    l.acquire()
    for _ in range(10):
        time.sleep(0.1)
        v.value += num
        print(v.value)
    l.release()
    
def multicore():
    l = mp.Lock()
    v = mp.Value('i', 0)
    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__':
    multicore()

结果:显然,进程锁保证了进程p1的完整运行,然后才进行了进程p2的运行

1
2
3
4
5
8
11
14
17
20
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值