如何使用Concurrent.futures实现循环迭代并行执行提速
问题原因
你当前的写法没有实现并行加速的核心原因是:你把整个matching函数作为单个任务提交给了线程池,全程只有1个工作线程在执行完整的循环逻辑,其余配置的worker完全处于闲置状态,根本没有参与计算。同时你提交任务后没有调用future.result(),就算任务执行完也拿不到最终的匹配结果。
正确实现方式
并行的核心是把可独立拆分的计算单元拆成单个子任务,分发给多个worker同时执行,而不是把整个计算逻辑打包成一个任务丢进线程池。
针对你的场景,完全可以把「列表a中单个字符串和列表b的多规则匹配」作为独立子任务拆分,分发给不同worker并行计算,最后在主线程合并结果即可。
修正后的可运行代码:
import random import string import tqdm from thefuzz import fuzz, process from concurrent.futures import ThreadPoolExecutor, as_completed def generate_string(items=10, lengths=5): # 修正原写法生成重复字符串的问题,返回独立随机字符串 return [''.join(random.choice(string.ascii_letters) for _ in range(lengths)) for _ in range(items)] # 单条字符串匹配逻辑,作为最小子任务分发 def match_single_item(x, candidate_list, scorers): best_score = 0 best_result = None for scorer in scorers.values(): res = process.extractOne(x, candidate_list, scorer=scorer) if res[1] > best_score: best_score = res[1] best_result = res return x, best_result def matching_parallel(a, b, max_workers=5): matches = {} scorers = { 'token_sort_ratio': fuzz.token_sort_ratio, 'token_set_ratio': fuzz.token_set_ratio, 'partial_token_sort_ratio': fuzz.partial_token_sort_ratio, 'Quick': fuzz.QRatio, 'Unicode Quick': fuzz.UQRatio, 'Weighted': fuzz.WRatio, 'Unweighted': fuzz.UWRatio } with ThreadPoolExecutor(max_workers=max_workers) as executor: # 为每个待匹配字符串提交独立任务 futures = [executor.submit(match_single_item, x, b, scorers) for x in a] # 按任务完成顺序更新进度、收集结果 for future in tqdm.tqdm(as_completed(futures), total=len(futures)): x, res = future.result() matches[x] = res return matches if __name__ == "__main__": list_a = generate_string(100, 10) list_b = generate_string(10, 5) final_matches = matching_parallel(list_a, list_b, max_workers=5)
注意事项
- 原代码里的
generate_string写法有误:[xxx] * items会把同一个字符串对象重复引用N次,列表内所有元素完全一致,用这种数据测试性能没有参考意义,修正版已经改成生成真正独立的随机字符串。 - 如果你没给
thefuzz安装python-Levenshtein加速依赖,默认会跑纯Python实现的字符串匹配逻辑,这种场景受Python GIL锁限制,多线程不会有明显加速,直接把ThreadPoolExecutor换成ProcessPoolExecutor用多进程跑即可。注意用多进程时,任务函数必须定义在顶层作用域,保证可被序列化。 - 不要在子线程/子进程里直接修改外部共享的字典、列表这类可变对象,所有子任务只返回自身的计算结果,统一在主线程做结果合并,避免线程/进程安全问题导致的数据错乱。
- worker数不是越高越好:如果是CPU密集型计算,worker数设置为和CPU核心数一致即可,开太多反而会因为频繁的上下文切换拖慢整体速度。
内容的提问来源于stack exchange,提问作者artemis
相关产品推荐
相关产品推荐

