You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用tqdm与multiprocess时进度条致代码减速5倍,求优化方案

问题:tqdm结合多进程Pool导致Python 2.7代码运行速度骤降

我在Python 2.7的代码里用tqdm给多进程任务加了进度条,结果运行速度大幅下滑——没加进度条时单次运行要12秒,加了之后直接到57秒了。

无进度条的代码:

import multiprocessing as mp

p = mp.Pool()
combs = various combinations
result = p.map(self.parallelize, combs)
p.close()
p.join()

带进度条的代码:

from tqdm import tqdm
import multiprocessing as mp

p = mp.Pool()
combs = various combinations
result = list(tqdm(p.imap(self.parallelize, combs), total=5000))
p.close()
p.join()

想问问有没有更优的实现方式,能降低对代码运行速度的影响?


优化方案

先解释下为什么速度变慢:p.imap()和p.map()的核心区别是,map()会一次性返回所有任务的结果,而imap()是逐个返回结果。你用tqdm包裹imap()时,每收到一个结果就会更新一次终端进度条——频繁的终端IO操作加上多进程间的小数据通信开销,叠加起来就把整体速度拖慢了。

下面给你几个实用的优化方法:

1. 给tqdm设置batch_size减少更新频率

不用每完成一个任务就更新进度条,而是积累一批结果后再更新,这样能大幅降低IO开销。调整后的代码:

from tqdm import tqdm
import multiprocessing as mp

p = mp.Pool()
combs = various combinations
# 比如每10个任务完成后更新一次进度条,数值可根据任务耗时调整
result = list(tqdm(p.imap(self.parallelize, combs), total=5000, batch_size=10))
p.close()
p.join()

batch_size越大,进度条更新次数越少,速度就越接近原生p.map()的表现。如果你的单个任务耗时很短,可以把这个值设得更大(比如100),效果会更明显。

2. 改用apply_async结合回调实时更新进度

用apply_async逐个提交任务,每个任务完成后触发回调更新进度条,避开imap()逐个返回的额外开销。示例代码:

from tqdm import tqdm
import multiprocessing as mp

p = mp.Pool()
combs = various combinations
total_tasks = 5000

# 初始化进度条
pbar = tqdm(total=total_tasks)

def update_progress(_):
    # 每完成一个任务,进度条前进1格
    pbar.update(1)

# 逐个提交异步任务并绑定回调
async_results = []
for comb in combs:
    res = p.apply_async(self.parallelize, args=(comb,), callback=update_progress)
    async_results.append(res)

# 等待所有任务完成并收集结果
final_result = [res.get() for res in async_results]

# 收尾操作
pbar.close()
p.close()
p.join()

这种方式的进度更新是异步的,不会阻塞主进程,进程间通信的开销也比imap()小很多。

3. 尝试tqdm的多进程专用工具(版本支持时)

如果你的Python 2.7能安装到较新版本的tqdm(比如>=4.28.0),可以用tqdm.contrib.concurrent里的process_map,它内部已经做了多进程和进度条的优化,不用自己手动管理Pool:

from tqdm.contrib.concurrent import process_map
import multiprocessing as mp

combs = various combinations
result = process_map(self.parallelize, combs, total=5000, max_workers=mp.cpu_count())

这个方法的速度损耗最小,因为它已经处理了进程间通信和进度条更新的平衡问题。

最后提一句:Python 2.7已经停止维护好几年了,如果条件允许,升级到Python 3.x会有更多高效的工具和更好的性能哦。


内容的提问来源于stack exchange,提问作者0_o

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:04:08