抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

R中可以方便的使用多进程, Python中也有类似的东西.

首先引用廖雪峰的Python教程解释一下进程和线程:

对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程,打开一个Word就启动了一个Word进程。

有些进程还不止同时干一件事,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)。

由于每个进程至少要干一件事,所以,一个进程至少有一个线程。当然,像Word这种复杂的进程可以有多个线程,多个线程可以同时执行,多线程的执行方式和多进程是一样的,也是由操作系统在多个线程之间快速切换,让每个线程都短暂地交替运行,看起来就像同时执行一样。当然,真正地同时执行多线程需要多核CPU才可能实现。

我们前面编写的所有的Python程序,都是执行单任务的进程,也就是只有一个线程。如果我们要同时执行多个任务怎么办?
有两种解决方案:
一种是启动多个进程,每个进程虽然只有一个线程,但多个进程可以一块执行多个任务。

还有一种方法是启动一个进程,在一个进程内启动多个线程,这样,多个线程也可以一块执行多个任务。

当然还有第三种方法,就是启动多个进程,每个进程再启动多个线程,这样同时执行的任务就更多了,当然这种模型更复杂,实际很少采用。

我需要执行的任务并不是IO等待很久的, 所以没有选择Python的多线程或者协程, 而是用多进程进行尝试

主要的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from multiprocessing import Pool

def func_to_process(args):
do someting
return result


def main():
sub_procs = Pool(10) # 10是使用的子进程数
results = [] # 用来存结果
for obj in iterable:
result = sub_procs.apply_async(func_to_process, (args))
# 提交任务到进程池, apply_async代表等待提交任务完成, 直接继续提交
# 直到进程池填满后阻塞
results.append(result)
sub_procs.close() # 关闭进程池, 不再能提交新任务
sub_procs.join() # 等待所有进程完毕, 这是为了下面正确的取回结果
results = [result.get() for result in results] # 使用get()取出所有结果


if __name__ == "__main__":
main()

这段代码存在两个问题:

  1. 这种写法等于把我要处理的文件按照行数拆分并执行, 每一行就进程, 拆得太碎了. 尤其是在执行的任务中如果有比较长时间的准备步骤时, 这么做其实会大大降低效率(单进程只准备一次, 而多进程准备无数次)
  2. 这样执行后, 结果顺序是有可能打乱的, 如果任务要求结果保持一定顺序, 则需要对接过再次排序

对于问题1, 经过今天学习, 可能是可以通过itertools中的部分功能实现对原文件的定量拆分的, 预计明天更新

对于问题2, 可以使用对应的map方法代替apply, 这个需要再进行尝试

评论

留下友善的评论吧~