python包-multiprocessing

我目前只掌握了这个包的一些用法,还有很多不清楚的地方。

据说python的多线程是假的,不能有效利用多核,一个时间只有一个线程在跑。因此平行计算只能使用多进程的技术。

这里我一般就是使用 pool 创建进程池。

为什么要用进程池

如果每个任务使用一个进程,每处理一个任务都会伴随着一个进程的创建、运行、销毁,如果进程的运行时间越短,创建和销毁的时间所占的比重就越大,显然,我们应该尽量避免创建和销毁进程本身的额外开销,提高进程的运行效率。我们可以用进程池来减少进程的创建和开销,提高进程对象的复用。

apply 和 apply_async

  • apply不推荐): 阻塞,堵塞的意思是说等待当前子进程执行完毕之后再执行下一个进程。

    首先主进程开始运行,碰到子进程,操作系统切换到子进程,等待子进程运行结束后,在切换到另外一个子进程,直到所有子进程运行完毕。然后在切换到主进程,运行剩余的部分。

    相当于还是单进程,串行计算,没有使用余地

  • apply_async : 非阻塞

    需要配合使用 pool.close()pool.join() ,这两部分是及时我们要告诉主进程,你等着所有子进程运行完毕后再运行剩余部分。这两个命令的官方文档说明如下

    1
    2
    3
    4
    5
    6
    close()
    阻止后续任务提交到进程池,当所有任务执行完成后,工作进程会退出。


    join()
    等待工作进程结束。调用 join() 前必须先调用 close() 或者 terminate() 。
  • mapmap_async 大同小异,不过接的参数是列表。

获取结果

首先,多进程函数要将结果写到 return 中(return 默认为 None,如果有多个值可以返回一个列表对象)。然后可以写到 一个列表中,提取列表元素时要用 get() ,才能得到值。

注意:

  1. 多进程中的子进程不会返回报错信息,只有在主进程用get方法来获取返回值时,子进程中的异常才会正常抛出。

  2. 由于子进程会拷贝父进程的所有状态,因此对于大文件会占用很多内存。为了避免这一点,可以先把大文件拆分为很多小的子文件,然后用子进程读取每个子文件。

  3. 杀死父进程时,子进程会变成孤儿进程,这一点我暂时还有解决方法。

举例

下面是我常用的多进程的例子,这个例子是打印 1- 20 这 20 个数字,每打印一个数字睡眠 1 秒。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import multiprocessing

def test(i):
import time # 多进程中需要在函数中调用需要的模块
time.sleep(1)
return(i)

result_list = [] # 后面两步合并结果的临时列表

#设置进程数
process_nums = 5
pool = multiprocessing.Pool(process_nums)
for i in range(1,11):
result_list.append(pool.apply_async(func=test, args=(i,)))
pool.close()
pool.join()

#可以继续写入结果列表中
process_nums = 5
pool = multiprocessing.Pool(process_nums)
for i in range(11,21):
result_list.append(pool.apply_async(func=test, args=(i,)))
pool.close()
pool.join()

for i in result_list:
print(i.get()) # 获得多进程结果

如果不使用多进程,正常串行运算的话,运行时间肯定在 20 秒以上,但是这里使用 5 个进程,运行时间只有 4 秒左右(20/5=4)。

1
2
3
In [18]: %timeit %run test.py
...
4.06 s ± 2.94 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

参考文献

  1. https://blog.csdn.net/hellenlee22/article/details/90643200

  2. https://blog.csdn.net/Bryan__/article/details/78786648

  3. https://zhuanlan.zhihu.com/p/340657122

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2019-2024 Vincere Zhou
  • 访问人数: | 浏览次数:

请我喝杯茶吧~

支付宝
微信