经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Python » 查看文章
深入解析Python中的多进程
来源:jb51  时间:2022/6/20 19:07:50  对本文有异议

前言

现在我们的计算机都是多个核的,通俗来说就是多个处理或者计算单元。为了加快运算和处理速度,我们可以将不同的任务交给多个核心进行同时处理,从而提高了运算速度和效率,多个核心同时运作就是多个进程同时进行,这就是多进程。

1.创建进程

创建进程和创建线程的方法基本一致,请看下面代码:

  1. # coding:utf-8
  2. # 导入多进程的包,并重命名为mp
  3. import multiprocessing as mp
  4. # 主要工作
  5. def p1():
  6. print("zxy")
  7. if __name__ == "__main__":
  8. # 创建新进程
  9. new_process = mp.Process(target=p1, name="p1")
  10. # 启动这个进程
  11. new_process.start()
  12. # 阻塞该进程
  13. new_process.join()

控制台效果图:

2.多进程中的Queue

为什么要在多进程中使用queue呢?
因为多进程和多线程一样,在工作函数中,无法通过return返回进程函数中的结果,所以使用queue进行存储结果,要用的时候再进行取出。

  1. # coding:utf-8
  2. import time
  3. import multiprocessing as mp
  4. """
  5. 使用多进程时,运行程序所用的时间
  6. """
  7. def job1(q):
  8. res = 0
  9. for i in range(100):
  10. res += i + i**5 +i**8
  11. time.sleep(0.1)
  12. # 将结果放入队列中
  13. q.put(res)
  14. def job2(q):
  15. res = 0
  16. for i in range(100):
  17. res += i + i**5 +i**8
  18. time.sleep(0.1)
  19. q.put(res)
  20. if __name__ == "__main__":
  21. start_time = time.time()
  22. # 创建队列
  23. q = mp.Queue()
  24. # 创建进程1
  25. process1 = mp.Process(target=job1, args=(q,))
  26. # 创建进程2
  27. process2 = mp.Process(target=job2, args=(q,))
  28. process1.start()
  29. process2.start()
  30. # 通过队列获取值
  31. res1 = q.get()
  32. res2 = q.get()
  33. print("res1为%d,res2为%d" % (res1, res2))
  34. end_time = time.time()
  35. print("整个过程所用时间为%s" %(end_time-start_time))

效果图:

3.多进程与多线程的性能比较

接下来使用多进程、多线程、以及什么都不用的普通方法进行处理,看看他们三种方法的效率如何?

  1. # coding:utf-8
  2. import multiprocessing as mp
  3. import time
  4. import threading as th
  5. """
  6. 多进程、多线程、普通方法的性能比较
  7. """
  8. # 多进程工作
  9. def mp_job(res):
  10. for i in range(10000000):
  11. res += i**5 + i**6
  12. print(res)
  13. # 多线程工作
  14. def mt_job(res):
  15. for i in range(10000000):
  16. res += i**5 + i**6
  17. print(res)
  18. # 普通方法工作
  19. def normal_job(res):
  20. for i in range(10000000):
  21. res += i ** 5 + i ** 6
  22. print(res)
  23. if __name__ == "__main__":
  24. mp_sum = 0
  25. mp_start = time.time()
  26. process1 =mp.Process(target=mp_job, args=(mp_sum, ))
  27. process2 = mp.Process(target=mp_job, args=(mp_sum,))
  28. process1.start()
  29. process2.start()
  30. process1.join()
  31. process2.join()
  32. mp_end = time.time()
  33. print("多进程使用时间为", (mp_end-mp_start))
  34. mt_start = time.time()
  35. mt_sum = 0
  36. thread1 = th.Thread(target=mt_job, args=(mt_sum, ))
  37. thread2 = th.Thread(target=mt_job, args=(mt_sum, ))
  38. thread1.start()
  39. thread2.start()
  40. thread1.join()
  41. thread2.join()
  42. mt_end = time.time()
  43. print("多线程使用的时间是", (mt_end-mt_start))
  44. normal_start = time.time()
  45. normal_sum = 0
  46. # 进行两次
  47. normal_job(normal_sum)
  48. normal_job(normal_sum)
  49. normal_end = time.time()
  50. print("普通方法使用的时间是", (normal_end-normal_start))

效果图:

实验结果表明:多进程的效率确实高!!!

4.进程池pool

进程池是干什么用的呢?
进程池就是python的多进程提供的一个池子,将所有的进程都放在这个池子里面,让计算机自己去使用进程池中的资源,从而多进程处理一些程序,进而提高工作效率。

(1)默认使用进程池中全部进程时

  1. # coding:utf-8
  2. import time
  3. import multiprocessing as mp
  4. """
  5. 进程池pool的使用
  6. """
  7. def job(num):
  8. time.sleep(1)
  9. return num * num
  10. if __name__ == "__main__":
  11. start_time = time.time()
  12. # 括号里面不加参数时,默认使用进程池中所有进程
  13. pool = mp.Pool()
  14. res = pool.map(job, range(10))
  15. print(res)
  16. end_time = time.time()
  17. print("运行时间为", (end_time-start_time))

效果图:

(2)指定进程池中进程数时

  1. # coding:utf-8
  2. import time
  3. import multiprocessing as mp
  4. """
  5. 进程池pool的使用
  6. """
  7. def job(num):
  8. time.sleep(1)
  9. return num * num
  10. if __name__ == "__main__":
  11. start_time = time.time()
  12. # 括号里面加参数时,指定两个进程进行处理
  13. pool = mp.Pool(processes=2)
  14. res = pool.map(job, range(10))
  15. print(res)
  16. end_time = time.time()
  17. print("运行时间为", (end_time-start_time))

效果图:

(3)不使用多进程时

  1. # coding:utf-8
  2. import time
  3. def job(res):
  4. for i in range(10):
  5. res.append(i*i)
  6. time.sleep(1)
  7. if __name__ == "__main__":
  8. start_time = time.time()
  9. res = []
  10. job(res)
  11. print(res)
  12. end_time =time.time()
  13. print("不使用进程池所用时间为", (end_time-start_time))

效果图:

实验结论:多进程处理事情,效率很高!!!核心越多,处理越快!

5.共享内存

一个核心,我们多线程处理时,可以使用全局变量来共享数据。但是多进程之间是不行的,那我们多进程之间应该如何共享数据呢?
那就得用到共享内存了!

  1. # coding:utf-8
  2. import multiprocessing as mp
  3. """
  4. 共享内存
  5. """
  6. if __name__ == "__main__":
  7. # 第一个参数是数据类型的代码,i代表整数类型
  8. # 第二个参数是共享数据的值
  9. v = mp.Value("i", 0)

6.进程锁lock

进程锁和线程锁的用法基本一致。进程锁的诞生是为了避免多进程之间抢占共享数据,进而造成多进程之间混乱修改共享内存的局面。

(1)不加锁之前

  1. # coding:utf-8
  2. import multiprocessing as mp
  3. import time
  4. """
  5. 进程中的锁lock
  6. """
  7. def job(v, num):
  8. for i in range(10):
  9. v.value += num
  10. print(v.value)
  11. time.sleep(0.2)
  12. if __name__ == "__main__":
  13. # 多进程中的共享内存
  14. v = mp.Value("i", 0)
  15. # 进程1让共享变量每次加1
  16. process1 = mp.Process(target=job, args=(v, 1))
  17. # 进程2让共享变量每次加3
  18. process2 = mp.Process(target=job, args=(v, 3))
  19. process1.start()
  20. process2.start()

效果图:

(2)加锁之后

  1. # coding:utf-8
  2. import multiprocessing as mp
  3. import time
  4. """
  5. 进程中的锁lock
  6. """
  7. def job(v, num, l):
  8. # 加锁
  9. l.acquire()
  10. for i in range(10):
  11. v.value += num
  12. print(v.value)
  13. time.sleep(0.2)
  14. # 解锁
  15. l.release()
  16. if __name__ == "__main__":
  17. # 创建进程锁
  18. l = mp.Lock()
  19. # 多进程中的共享内存
  20. v = mp.Value("i", 0)
  21. process1 = mp.Process(target=job, args=(v, 1, l))
  22. process2 = mp.Process(target=job, args=(v, 3, l))
  23. process1.start()
  24. process2.start()

效果图:

到此这篇关于深入解析Python中的多进程的文章就介绍到这了,更多相关Python多进程内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号