Python multiprocessing主进程完成任务后退出耗时过长问题咨询
问题原因
你遇到的超长退出耗时是两个代码bug共同导致的,和multiprocessing本身的终止流程无关:
- 核心判断逻辑永远不会触发
你的getPassword函数匹配到目标密码后,仅在工作进程内执行了打印操作,没有返回匹配到的密码字符串。主进程遍历imap_unordered返回的迭代器时,拿到的所有result值都是None,if result == userPass判断恒为False,你写的pool.terminate()根本没有被执行。你看到的70秒破解提示是工作进程直接输出的,此时主进程还在等待所有工作进程执行完分配到的全部任务,自然会产生大量额外耗时。 - chunksize参数计算完全错误,数值过大
你注释标注要计算「最优分块数」,但imap_unordered的chunksize参数含义是单次发送给单个工作进程的任务数量,不是总块数。按你的计算逻辑,6位小写字母总组合数为26^6=308915776,以8核CPU为例,算出来的chunksize值接近965万,也就是每个工作进程一次要领取近千万个任务执行。就算你修复了返回值问题,工作进程必须把手上整个chunk的所有任务全部跑完,才会把结果回传给主进程,主进程才能触发终止逻辑,这期间的等待时间就是工作进程跑完剩余chunk任务的耗时,刚好和你观察到的「破解耗时70秒、总耗时160秒」的现象吻合。
修复方案
按以下步骤修改代码即可解决问题:
- 给
getPassword函数增加返回值,匹配到密码时返回对应字符串,未匹配返回None - 调小chunksize数值,对于这类单任务执行极快的CPU密集场景,chunksize设为1000~10000即可,保证任务调度粒度足够细,找到结果后可以立刻触发终止,不需要等工作进程跑完超大批次任务
- 不需要手动
del result,迭代器本身会按顺序释放内存,这个操作没有实际作用
修复后的完整代码如下:
import itertools import multiprocessing as mp import string import time tStart = time.time() userPass = 'mypass' def getPassword(passList): pwd = ''.join(passList) if userPass == pwd: print('\n') print('~~~ CRACKED ~~~') print('User password is {}'.format(pwd)) print('Cracked password in {:.3f} seconds'.format(time.time() - tStart)) return pwd return None if __name__ == '__main__': chars = list(string.ascii_lowercase) allPasswords = itertools.product(chars, repeat=len(userPass)) # 设为合理的小块大小,保证调度灵活性 chunksize = 10000 with mp.Pool(processes=mp.cpu_count()) as pool: for result in pool.imap_unordered(getPassword, allPasswords, chunksize=chunksize): if result == userPass: pool.terminate() break tEnd = time.time() tElapsed = tEnd - tStart print('Total elapsed time {:.3f} seconds'.format(tElapsed))
修复后找到密码触发terminate时,工作进程只会剩余极少量未完成的小块任务,额外退出耗时通常在1秒以内,总耗时会和实际破解耗时基本一致。
内容的提问来源于stack exchange,提问作者2nsis
相关产品推荐
相关产品推荐

