python进阶之多进程

  • 2019 年 10 月 5 日
  • 笔记

python进阶之多进程

0.导语1.进程与线程初识1.1 导包1.2 定义被调函数1.3 创建线程和进程1.4 启动线程和进程2.输出结果存放至Queue2.1 导包2.2 定义被调函数2.3 启动多进程,存放结果3.进程与线程效率对比3.1 导入多进程包3.2 定义被调函数3.3 封装多进程3.4 导入线程包3.5 封装多线程3.6 封装普通方法3.7 主函数调用3.8 输出结果4.进程池4.1 导入进程包4.2 定义被调函数4.3 封装函数4.4 主函数调用5.共享内存6.进程锁6.1 不同进程争夺资源6.2 通过锁机制解决争夺资源问题7.参考资料

0.导语

今天来学习python进阶知识,一起来实战嗨起来~ 欢迎留言,哈哈,我会对经常留言的后面发福利!

1.进程与线程初识

1.1 导包

# 导入线程进程标准模块  import multiprocessing as mp  import threading as td  

1.2 定义被调函数

# 定义一个被线程和进程调用的函数  def job(a,d):      print('aaaaa')  

1.3 创建线程和进程

# 创建线程和进程  t1 = td.Thread(target=job, args=(1,2)) # (1,2,)与(1,2)一样效果  p1 = mp.Process(target=job, args=(1,2)) # (1,2,)与(1,2)一样效果  

1.4 启动线程和进程

if __name__ == '__main__':      # 启动线程和进程      t1.start()      p1.start()      # 连接线程和进程      t1.join()      p1.join()  

2.输出结果存放至Queue

2.1 导包

import multiprocessing as mp  

2.2 定义被调函数

这里传入Queue对象

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

2.3 启动多进程,存放结果

if __name__ == '__main__':      q = mp.Queue()      p1 = mp.Process(target=job, args=(q,))      p2 = mp.Process(target=job, args=(q,))      p1.start()      p2.start()      p1.join()      p2.join()      res1 = q.get()      res2 = q.get()      print(res1+res2)  

3.进程与线程效率对比

3.1 导入多进程包

import multiprocessing as mp  

3.2 定义被调函数

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

3.3 封装多进程

# 多核/多进程  def multicore():      q = mp.Queue()      p1 = mp.Process(target=job, args=(q,))      p2 = mp.Process(target=job, args=(q,))      p1.start()      p2.start()      p1.join()      p2.join()      res1 = q.get()      res2 = q.get()      print('multicore:', res1 + res2)  

3.4 导入线程包

import threading as td  

3.5 封装多线程

# 多线程  def multithread():      q = mp.Queue()      t1 = td.Thread(target=job, args=(q,))      t2 = td.Thread(target=job, args=(q,))      t1.start()      t2.start()      t1.join()      t2.join()      res1 = q.get()      res2 = q.get()      print('multithread:', res1 + res2)  

3.6 封装普通方法

def normal():      res = 0      for _ in range(2):          for i in range(1000000):              res += i + i ** 2 + i ** 3      print('normal:',res)  

3.7 主函数调用

三种方法对比效率

import time  if __name__ == '__main__':      st = time.time()      normal()      st1 = time.time()      print('normal time:', st1 - st)      multithread()      st2 = time.time()      print('multithread time:', st2 - st1)      multicore()      st3 = time.time()      print('multicore time:', st3 - st2)  

3.8 输出结果

normal: 499999666667166666000000  normal time: 1.779979944229126  multithread: 499999666667166666000000  multithread time: 1.8090195655822754  multicore: 499999666667166666000000  multicore time: 1.2929792404174805  

结论:多进程 < 普通 < 多线程

4.进程池

说在前面:有了池子之后,就可以让池子对应某一个函数,我们向池子里丢数据,池子就会返回函数返回的值。

Pool和之前的Process的不同点是丢向Pool的函数有返回值,而Process的没有返回值。

4.1 导入进程包

import multiprocessing as mp  

4.2 定义被调函数

def job(x):      return x*x  

4.3 封装函数

map() 与 apply_async() 两种方式 返回结果

def multicore():      '''      Pool默认调用是CPU的核数,传入processes可自定义CPU核数      map()放入迭代参数,返回多个结果      apply_async()只能放入一组参数,并返回一个结果,如果想得到map()的效果需要通过迭代      '''      pool = mp.Pool(processes=2)      res = pool.map(job, range(10))      print(res)      '''      apply_async()只能传递一个值,它只会放入一个核进行运算,传入的值因为必须是可迭代的,      所以在传入值后需要加逗号,同时需要用get()方法获取返回值。      '''      res = pool.apply_async(job, (2,))      multi_res = [pool.apply_async(job, (i,)) for i in range(10)]      print(res.get()) # 获取单个结果      print([res.get() for res in multi_res]) # 获取多个结果  

4.4 主函数调用

if __name__ == '__main__':      multicore()  

5.共享内存

import multiprocessing as mp    '''  使用Value数据存储在一个共享的内存表中  d表示一个双精浮点类型,i表示一个带符号的整型  '''  value1 = mp.Value('i', 0)  value2 = mp.Value('d', 3.14)    '''  Array类,可以和共享内存交互,来实现在进程之间共享数据。  这里的Array和numpy中的不同,它只能是一维的,不能是多维的。  同样和Value 一样,需要定义数据形式,否则会报错。  '''  array = mp.Array('i', [1,2,3,4])  

6.进程锁

6.1 不同进程争夺资源

import multiprocessing as mp  import time  def job(v, num):      for _ in range(5):          time.sleep(0.1)          v.value += num          print(v.value,end="n")    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()  

6.2 通过锁机制解决争夺资源问题

import multiprocessing as mp  import time  def job(v, num, l):      l.acquire() # 锁住      for _ in range(5):          time.sleep(0.1)          v.value += num          print(v.value,end="n")      l.release() # 释放    def multicore():      l = mp.Lock() # 定义一个进程锁      v = mp.Value('i',0) # 定义共享变量      p1 = mp.Process(target=job, args=(v,1,l)) # 需要将lock传入      p2 = mp.Process(target=job, args=(v,3,l)) # 设定不同的number看如何抢夺内存      p1.start()      p2.start()      p1.join()      p2.join()    if __name__ == '__main__':      multicore()  

7.参考资料

https://morvanzhou.github.io/tutorials/python-basic/multiprocessing/