ProcessPoolExecutor并行编程
发布网友
发布时间:2022-12-26 10:03
我来回答
共1个回答
热心网友
时间:2023-10-15 10:20
你有个程序要执行CPU密集型工作,你想让他利用多核CPU的优势来运行的快一点。
concurrent.futures 库提供了一个 ProcessPoolExecutor 类, 可被用来在一个单独的Python解释器中执行计算密集型函数。 不过,要使用它,你首先要有一些计算密集型的任务。 我们通过一个简单而实际的例子来演示它。假定你有个Apache web服务器日志目录的gzip压缩包:
进一步假设每个日志文件内容类似下面这样:
下面是一个脚本,在这些日志文件中查找出所有访问过robots.txt文件的主机:
前面的程序使用了通常的map-rece风格来编写。 函数 find_robots() 在一个文件名集合上做map操作,并将结果汇总为一个单独的结果, 也就是 find_all_robots() 函数中的 all_robots 集合。 现在,假设你想要修改这个程序让它使用多核CPU。 很简单——只需要将map()操作替换为一个 concurrent.futures 库中生成的类似操作即可。 下面是一个简单修改版本:
通过这个修改后,运行这个脚本产生同样的结果,但是在四核机器上面比之前快了3.5倍。 实际的性能优化效果根据你的机器CPU数量的不同而不同。
ProcessPoolExecutor 的典型用法如下:
其原理是,一个 ProcessPoolExecutor 创建N个独立的Python解释器, N是系统上面可用CPU的个数。你可以通过提供可选参数给 ProcessPoolExecutor(N) 来修改 处理器数量。这个处理池会一直运行到with块中最后一个语句执行完成, 然后处理池被关闭。不过,程序会一直等待直到所有提交的工作被处理完成。
被提交到池中的工作必须被定义为一个函数。有两种方法去提交。 如果你想让一个列表推导或一个 map() 操作并行执行的话,可使用 pool.map() :
另外,你可以使用 pool.submit() 来手动的提交单个任务:
如果你手动提交一个任务,结果是一个 Future 实例。 要获取最终结果,你需要调用它的 result() 方法。 它会阻塞进程直到结果被返回来。
如果不想阻塞,你还可以使用一个回调函数,例如:
回调函数接受一个 Future 实例,被用来获取最终的结果(比如通过调用它的result()方法)。 尽管处理池很容易使用,在设计大程序的时候还是有很多需要注意的地方,如下几点:
一旦启动你不能控制子进程的任何行为,因此最好保持简单和纯洁——函数不要去修改环境。
它会克隆Python解释器,包括fork时的所有程序状态。 而在Windows上,克隆解释器时不会克隆状态。 实际的fork操作会在第一次调用 pool.map() 或 pool.submit() 后发生。
你应该在创建任何线程之前先创建并激活进程池(比如在程序启动的main线程中创建进程池)。
Python并行编程:subprocess、ProcessPoolExecutor
以计算列表元素0到每个元素值的平方和为例,ProcessPoolExecutor可以简化代码,实现并行计算。然而,对于性能要求极高(如100us级别)的应用,Python可能不是首选语言,因为其他语言可能更适合处理这类高并发场景。总的来说,Python并行编程需结合subprocess和ProcessPoolExecutor等工具,但要注意GIL的限制。在实...
ProcessPoolExecutor并行编程
ProcessPoolExecutor 的典型用法如下:其原理是,一个 ProcessPoolExecutor 创建N个独立的Python解释器, N是系统上面可用CPU的个数。你可以通过提供可选参数给 ProcessPoolExecutor(N) 来修改 处理器数量。这个处理池会一直运行到with块中最后一个语句执行完成, 然后处理池被关闭。不过,程序会一直...
python并行编程之Asyncio
接着,文章深入介绍了Python中的并发编程技术。多线程通过`thread`和`ThreadPoolExecutor`实现,允许在同一进程内创建多个线程来执行并行任务。而多进程则通过`subprocess`和`ProcessPoolExecutor`实现,每个进程拥有独立的地址空间,避免了线程间的资源竞争问题,适合于计算密集型任务。最后,文章聚焦于Python并行...
Future, ThreadPoolExecutor和ProcessPoolExecutor
ThreadPoolExecutor和ProcessPoolExecutor是Executor类的子类,分别使用线程池和进程池执行异步任务。ThreadPoolExecutor默认线程数为CPU核心数乘以5,适用于IO密集型工作,工作者数量通常多于ProcessPoolExecutor。ProcessPoolExecutor最多使用指定的最大进程数,若未指定默认为CPU核心数,且最大进程数不能为0,否则...
python中的asyncio使用详解与异步协程的处理流程分析
使用 concurrent.futures 下的 ThreadPoolExecutor 或 ProcessPoolExecutor 可在多线程或多进程中执行同步函数。注意它们在初始化时的 max_workers 参数决定执行器的工作线程数。异步函数的动态添加 使用 asyncio.run_coroutine_threadsafe() 可以将协程绑定到事件循环上,避免阻塞主线程。通过 gather() 方法...
Asyncio 异步编程模块-Python成为专业人士笔记
在Python云环境中,异步编程可以通过async函数和Executor来实现。例如,run_in_executor()使用Executor在异步任务中执行代码,ThreadPoolExecutor和ProcessPoolExecutor可用于线程池和进程池的调度。对于性能优化,uvloop是一个基于libuv的高性能事件循环,尽管Windows上暂时不可用,但在云环境下安装后,可以提供显著...