为何两段Python多线程调用OpenAI API的代码性能差异巨大?
为什么Python多线程中直接调用
requests.post比封装后调用性能差异显著? 测试代码
import requests from concurrent.futures import ThreadPoolExecutor import time def process_payload(payload, url, headers): response = requests.post(url, headers=headers, json=payload) return response def parallel_group2(payloads, url, headers): with ThreadPoolExecutor() as executor: results = executor.map(process_payload,payloads, [url]*len(payloads), [headers]*len(payloads)) return list(results) def parallel_group(payloads, url, headers): with ThreadPoolExecutor() as executor: results = executor.map(requests.post, [url]*len(payloads), [headers]*len(payloads), payloads) return list(results) times = [] # payloads grouped by 15 payloads_grouped = [payloads[i:i+15] for i in range(0, len(payloads), 15)] print( "shape of payloads_grouped", len(payloads_grouped), " x ", len(payloads_grouped[0])) for i in range(3): start = time.time() with ThreadPoolExecutor() as executor: # results = executor.map(parallel_group2, payloads_grouped, [url]*len(payloads_grouped), [headers]*len(payloads_grouped)) results = executor.map(parallel_group, payloads_grouped, [url]*len(payloads_grouped), [headers]*len(payloads_grouped)) end = time.time() times.append(end-start) print( "Durations of iterations:", times) print( "Durations of iterations:", times) print( "Average time for 150 requests:", sum(times)/len(times))
测试结果
运行parallel_group时(直接调用requests.post)
Durations of iterations: [5.246389389038086, 5.195073127746582, 5.278628587722778] Average time for 150 requests: 5.2400303681691485
运行parallel_group2时(调用封装后的process_payload)
Durations of iterations: [10.99542498588562, 9.43007493019104, 23.003321170806885] Average time for 150 requests: 10.142940362294516
注:调用的接口为OpenAI的Chat Completion API(api.openai.com/v1/chat/completions),多次测试结果均保持一致。
原因分析
1. 参数传递错误导致请求逻辑差异(核心原因)
parallel_group函数中,使用executor.map调用requests.post时的参数传递完全错误:
requests.post的签名为requests.post(url, data=None, json=None, **kwargs),headers属于关键字参数,必须通过headers=headers的形式传递,不能作为位置参数传入。- 当前代码的调用等价于
requests.post(url, data=headers, json=payload),把headers当成了请求体的data参数,实际请求并没有携带你需要的授权头(如Authorization)。
这种错误导致parallel_group中的请求被OpenAI API直接拒绝(返回401类错误),无需执行实际的Chat Completion计算,因此处理时间大幅缩短。而parallel_group2中的process_payload函数正确传递了headers,请求会被正常处理,耗时更长。
2. 线程池嵌套的额外开销(次要因素)
即使修正参数传递问题,parallel_group2的嵌套线程池结构也会带来额外性能损耗:
- 外层线程池的每个线程都会创建并销毁一个内层线程池,增加了线程初始化、调度的重复开销。
- 过多的线程会提升上下文切换频率,当线程数量超过IO密集型场景的最优值(通常为CPU核心数的2~4倍)时,调度开销会抵消IO等待带来的并发收益,甚至导致性能骤降。
内容的提问来源于stack exchange,提问作者codeur rapide
相关产品推荐
相关产品推荐

