什么是多进程?

我们在多线程 (Threading) 里提到过, 它是有劣势的, GIL 让它没能更有效率的处理一些分摊的任务. 而现在的电脑大部分配备了多核处理器, 多进程 Multiprocessing 能让电脑更有效率的分配任务给每一个处理器, 这种做法解决了多线程的弊端. 也能很好的提升效率.

也就是 电脑有多核的处理器, 多核运算

1.2 创建进程 Process

  1. # 创建进程
  2. """
  3. 添加进程模块 multiprocessing
  4. 添加进程的 命令 Process
  5. target=job 表示 要执行的进程 函数名
  6. args=() 表示传入的 参数
  7. name="" 表示进程的名字
  8. """
  9. import multiprocessing as mp # 多进程模块
  10. import threading as td #多线程模块
  11. def job(a,b):
  12. print("aaaa",a,b)
  13. # 多线程 与多进程的命令对比
  14. if __name__ == "__main__":
  15. # t1= td.Thread(target=job, args=(1,2)) # 添加(创建)线程
  16. p1 = mp.Process(target=job, args=(1, 2)) # 添加(创建)进程
  17. # t1.start()
  18. # t1.join()
  19. p1.start()
  20. p1.join()

1.3 存储进程输出 Queue

  1. # 存储进程输出 Queue
  2. import multiprocessing as mp # 多进程模块
  3. def job(q):
  4. res = 0
  5. for i in range(1000):
  6. res += i + i**2 + i **3
  7. q.put(res)
  8. # 多线程 与多进程的命令对比
  9. if __name__ == "__main__":
  10. q =mp.Queue()
  11. p1 = mp.Process(target=job, args=(q,)) # 加逗号表示 这个可以迭代的东西
  12. p2 = mp.Process(target=job, args=(q,)) # 添加(创建)进程
  13. p1.start()
  14. p2.start()
  15. p1.join()
  16. p2.join()
  17. res1= q.get()
  18. res2= q.get()
  19. print(res1 + res2)
  20. ------------------------
  21. 499667166000

1.4 效率对比 threading & multiprocessing

  1. # 存储进程输出 Queue
  2. import multiprocessing as mp # 多进程模块
  3. import threading as td
  4. import time
  5. def job(q):
  6. res = 0
  7. for i in range(100000):
  8. res += i + i**2 + i **3
  9. q.put(res)
  10. # 多进程
  11. def multicore():
  12. q =mp.Queue()
  13. p1 = mp.Process(target=job, args=(q,)) # 加逗号表示 这个可以迭代的东西
  14. p2 = mp.Process(target=job, args=(q,)) # 添加(创建)进程
  15. p1.start()
  16. p2.start()
  17. p1.join()
  18. p2.join()
  19. res1= q.get()
  20. res2= q.get()
  21. print("multicore:",res1 + res2)
  22. # 多线程 与多进程结合
  23. def multithreading():
  24. q =mp.Queue()
  25. p1 = td.Thread(target=job, args=(q,)) # 加逗号表示 这个可以迭代的东西
  26. p2 = td.Thread(target=job, args=(q,)) # 添加(创建)进程
  27. p1.start()
  28. p2.start()
  29. p1.join()
  30. p2.join()
  31. res1= q.get()
  32. res2= q.get()
  33. print("multithreading",res1 + res2)
  34. def normal():
  35. res = 0
  36. for _ in range(2):
  37. for i in range(100000):
  38. res += i + i**2 + i **3
  39. print("normal", res)
  40. # 多线程 与多进程的命令对比
  41. if __name__ == "__main__":
  42. st = time.time()
  43. normal()
  44. st1 = time.time()
  45. print("normal time:", st1 - st)
  46. multithreading()
  47. st2 = time.time()
  48. print("multithreading time:", st2 - st1)
  49. multicore()
  50. print("multicore time:", time.time() - st2)
  51. ------------------------------
  52. normal 49999666671666600000
  53. normal time: 0.10569334030151367
  54. multithreading 49999666671666600000
  55. multithreading time: 0.13794255256652832
  56. multicore: 49999666671666600000
  57. multicore time: 0.26130223274230957

1.5 进程池 Pool

  1. # 进程池
  2. """
  3. .Pool() 默认使用系统的全部核
  4. .Pool(processes=2) 指定使用核数
  5. .pool.map() 可使用无限的参数
  6. .pool.apply_async() 只能传入1个参数
  7. """
  8. import multiprocessing as mp
  9. def job(x):
  10. return x*x
  11. def multicore():
  12. pool= mp.Pool() # 默认启动全部
  13. # pool = mp.Pool(processes=2) # processes 指定启动几个核进程
  14. # map 是可以放入很多个迭代的参数, 自动分配到进程,如果有2个进程,就自动分配
  15. res= pool.map(job,range(10))
  16. print(res)
  17. # apply_async 只能在一个进程里算一个东西,
  18. res = pool.apply_async(job,(2,)) # apply_async 只能传1个参数
  19. print(res.get())
  20. # 如果apply_async 想要达到map 的 效果, 就要把 apply_async 设置成迭代的效应,然后用迭代,把它的值传出来. 列表中的迭代 出来, 一个一个的拿出来
  21. multi_res = [pool.apply_async(job,(i,)) for i in range(10)]
  22. print([res.get() for res in multi_res])
  23. if __name__ == "__main__":
  24. multicore()
  25. ----------------------
  26. [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  27. 4
  28. [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

1.6 共享内存 shared memory

https://docs.python.org/3.5/library/array.html#module-array

  1. import multiprocessing as mp
  2. mp.Value("d", 1)
  3. mp.array("i", [1,2,3]) # 只能定义一维的 数组,不能定义多维的
类型 code C 类型 Python 类型 Minimum size in bytes Notes
“b” int 1
“B” int 1
“u” Unicode character 2 (1)
“h” int 2
“H” int 2
“i” int 2
“I” int 2
“l” int 4
“L” int 4
“q” int 8 (2)
“Q” int 8 (2)
“f” float 4
“d” float 8

1.7 进程锁

  1. # 抢共享内存
  2. import multiprocessing as mp
  3. import time
  4. def job(v,num,L):
  5. L.acquire() # 加入了锁 锁住进程
  6. for _ in range(10):
  7. time.sleep(0.1)
  8. v.value += num
  9. print(v.value)
  10. L.release() # 加入了锁 释放进程
  11. def multicore():
  12. l= mp.Lock() # 加入了锁
  13. v = mp.Value("i", 0)
  14. p1 = mp.Process(target=job, args=(v,1,l))
  15. p2 = mp.Process(target=job, args=(v,3,l))
  16. p1.start()
  17. p2.start()
  18. p1.join()
  19. p2.join()
  20. if __name__ == "__main__":
  21. multicore()
  22. --------------------不加进程锁___打印的很乱没有规律
  23. 1
  24. 5
  25. 9
  26. 13
  27. 17
  28. 21
  29. 25
  30. 29
  31. 33
  32. 37
  33. 4
  34. 8
  35. 12
  36. 16
  37. 20
  38. 24
  39. 28
  40. 32
  41. 36
  42. 40
  43. --------------------加入进程锁___打印的很规律
  44. 1
  45. 2
  46. 3
  47. 4
  48. 5
  49. 6
  50. 7
  51. 8
  52. 9
  53. 10
  54. 13
  55. 16
  56. 19
  57. 22
  58. 25
  59. 28
  60. 31
  61. 34
  62. 37
  63. 40