当前位置: 首页 > article >正文

《AI大模型应用开发实战从入门到精通共60篇》041、异步编程:用asyncio提升LLM应用的并发性能

041 异步编程用asyncio提升LLM应用的并发性能从一次线上事故说起凌晨两点告警电话把我从床上拽起来。监控显示我们的LLM对话服务响应时间从200ms飙到了8秒CPU负载却只有30%。查日志发现每次用户请求都在等上游的OpenAI接口返回——一个请求等2秒十个请求排队等20秒。同步阻塞典型的“一个人干活一群人围观”场景。这个问题的本质是LLM调用是I/O密集型操作网络延迟占大头。同步代码里线程在等待网络响应时啥也不干白白浪费CPU时间片。当时我盯着火焰图里那条长长的recvfrom调用链心想必须上异步了。asyncio到底在解决什么问题很多人把asyncio和“并发”划等号其实它解决的是等待时的资源复用。想象你在咖啡店排队点单同步模式是你站在柜台前等咖啡做好才让下一个人点异步模式是你点完单拿个号去旁边坐着服务员继续接待下一个人咖啡好了叫号。Python的GIL让多线程在CPU密集型任务上表现糟糕但对I/O密集型任务asyncio用单线程事件循环实现了比多线程更高效的并发。原因很简单线程切换有开销协程切换是用户态操作轻量得多。从同步到异步一个LLM调用的改造实录先看一个典型的同步LLM调用代码importrequestsimporttimedefcall_llm(prompt):# 这里踩过坑requests默认超时时间很长生产环境一定要设timeoutresprequests.post(https://api.openai.com/v1/chat/completions,json{model:gpt-3.5-turbo,messages:[{role:user,content:prompt}]},headers{Authorization:Bearer YOUR_KEY},timeout30)returnresp.json()# 串行调用10个请求要等20秒prompts[讲个笑话,写首诗,翻译成英文,...]results[]forpinprompts:results.append(call_llm(p))这段代码的问题每个call_llm都在阻塞等待网络响应10个请求依次执行总耗时 单个请求耗时 × 请求数。改成asyncio版本importasyncioimportaiohttp# 别用requests它不支持异步asyncdefcall_llm_async(session,prompt):# 注意aiohttp的session要复用别每次请求都创建新的asyncwithsession.post(https://api.openai.com/v1/chat/completions,json{model:gpt-3.5-turbo,messages:[{role:user,content:prompt}]},headers{Authorization:Bearer YOUR_KEY},timeoutaiohttp.ClientTimeout(total30))asresp:returnawaitresp.json()asyncdefmain():# 这里踩过坑connector参数控制连接池大小默认20并发高时要调大connectoraiohttp.TCPConnector(limit50)asyncwithaiohttp.ClientSession(connectorconnector)assession:prompts[讲个笑话,写首诗,翻译成英文,...]# 创建10个协程任务并发执行tasks[call_llm_async(session,p)forpinprompts]resultsawaitasyncio.gather(*tasks)returnresults# 运行事件循环starttime.time()resultsasyncio.run(main())print(f耗时{time.time()-start:.2f}秒)改造后10个请求几乎同时发出总耗时 ≈ 最慢的那个请求的耗时通常2-3秒。性能提升5-10倍。那些年我踩过的asyncio坑坑1在异步函数里调用同步阻塞代码asyncdefbad_example():# 别这样写time.sleep会阻塞整个事件循环time.sleep(5)returndoneasyncdefgood_example():# 正确做法用asyncio.sleep让出控制权awaitasyncio.sleep(5)returndone如果必须调用同步阻塞库比如某些数据库驱动用loop.run_in_executor把它扔到线程池里importconcurrent.futuresasyncdefcall_sync_db():loopasyncio.get_event_loop()# 这里踩过坑默认线程池大小是CPU核心数×5高并发场景要自定义withconcurrent.futures.ThreadPoolExecutor(max_workers20)aspool:resultawaitloop.run_in_executor(pool,sync_db_query)returnresult坑2忘记处理异常导致任务静默失败asyncio.gather默认会抛出第一个异常导致其他任务被取消。更稳妥的做法asyncdefsafe_gather():tasks[call_llm_async(session,p)forpinprompts]# return_exceptionsTrue让异常作为结果返回不会中断其他任务resultsawaitasyncio.gather(*tasks,return_exceptionsTrue)fori,rinenumerate(results):ifisinstance(r,Exception):print(f第{i}个请求失败{r})results[i]None# 用默认值替代returnresults坑3事件循环嵌套在Jupyter Notebook或某些框架里事件循环可能已经运行再调用asyncio.run()会报错。解决方案try:loopasyncio.get_running_loop()exceptRuntimeError:# 没有运行中的事件循环创建新的resultsasyncio.run(main())else:# 已有事件循环用create_taskresultsloop.run_until_complete(main())实战构建一个带限速的LLM并发调用器LLM API通常有速率限制比如每分钟60次并发太高会被限流甚至封号。我们需要一个带令牌桶的异步限速器importasyncioimporttimeclassRateLimiter:def__init__(self,max_calls,period60):self.max_callsmax_calls self.periodperiod self.tokensmax_calls self.last_refilltime.monotonic()self._lockasyncio.Lock()# 这里踩过坑必须用asyncio.Lock不是threading.Lockasyncdefacquire(self):asyncwithself._lock:nowtime.monotonic()elapsednow-self.last_refill# 按时间比例补充令牌self.tokensmin(self.max_calls,self.tokenselapsed*(self.max_calls/self.period))self.last_refillnowifself.tokens1:# 令牌不足计算需要等待的时间wait_time(1-self.tokens)*(self.period/self.max_calls)awaitasyncio.sleep(wait_time)self.tokens0else:self.tokens-1# 使用示例limiterRateLimiter(max_calls60,period60)# 每分钟60次asyncdefrate_limited_call(session,prompt):awaitlimiter.acquire()# 获取令牌可能等待returnawaitcall_llm_async(session,prompt)这个限速器用asyncio.Lock保证令牌操作的原子性用time.monotonic避免系统时间调整带来的问题。实际生产环境中我还会加上指数退避重试逻辑。性能调优从10倍到50倍基础异步改造能带来5-10倍提升但想榨干性能还需要几个技巧1. 连接复用aiohttp.ClientSession默认会复用TCP连接但要注意连接池大小。我一般根据API的并发限制来设置# 如果API允许100并发连接池设120留余量connectoraiohttp.TCPConnector(limit120,limit_per_host120)2. 请求合并对于流式输出SSE用aiohttp的content属性逐块读取避免等待完整响应asyncdefstream_llm(session,prompt):asyncwithsession.post(url,json{stream:True,...},headersheaders)asresp:asyncforchunkinresp.content:# 处理每个chunk实现打字机效果yieldchunk.decode()3. 使用uvloop加速uvloop是用Cython重写的事件循环性能比默认的asyncio事件循环快2倍importuvloop asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())# 然后正常使用asyncio.run()注意uvloop在Windows上支持有限生产环境建议在Linux上部署。个人经验建议别盲目全盘异步化。如果你的服务主要是CPU计算比如图像处理、模型推理异步带来的收益有限反而增加代码复杂度。异步最适合I/O密集且并发高的场景。异步代码的调试是个噩梦。asyncio.gather里的异常堆栈经常指向事件循环内部而不是你的业务代码。我的做法是每个协程函数都加try/except用logging.exception记录完整上下文再重新抛出或返回错误码。注意内存泄漏。异步代码里容易忘记释放资源特别是aiohttp.ClientSession。始终用async with管理资源或者显式调用session.close()。监控要跟上。异步服务的性能指标和同步服务不同要关注事件循环的延迟event loop lag、协程队列长度、连接池使用率。我习惯在关键路径上埋点记录每个协程的等待时间和执行时间。从同步到异步的迁移策略不要一次性重写所有代码。先找出I/O瓶颈最严重的模块比如LLM调用、数据库查询用异步重写其他部分保持同步。用run_in_executor作为过渡桥梁。最后说一句asyncio不是银弹但对付LLM这种高延迟、高并发的I/O场景它确实是最趁手的工具。下次你的服务再因为同步阻塞而告警试试把requests换成aiohttp把time.sleep换成asyncio.sleep——你会回来感谢我的。

相关文章:

《AI大模型应用开发实战从入门到精通共60篇》041、异步编程:用asyncio提升LLM应用的并发性能

041 异步编程:用asyncio提升LLM应用的并发性能 从一次线上事故说起 凌晨两点,告警电话把我从床上拽起来。监控显示我们的LLM对话服务响应时间从200ms飙到了8秒,CPU负载却只有30%。查日志发现,每次用户请求都在等上游的OpenAI接口返…...

避开“毒王”分子:药物化学家如何利用警示子结构(SA)库提前规避研发雷区

药物化学家的结构排雷指南:如何利用警示子结构规避研发风险 在药物研发的漫长征程中,化学家们常常面临一个残酷的现实:约90%的候选药物最终未能通过临床试验,其中近半数折戟于安全性问题。那些看似微小的分子片段——一个苯环上的…...

小龙虾算法COA实战:调参指南与在CEC2005测试函数上的表现分析

小龙虾优化算法COA实战:参数调优与性能评估全解析 在智能优化算法的研究领域,生物启发式算法因其独特的搜索机制和解决复杂问题的能力而备受关注。小龙虾优化算法(Crayfish Optimization Algorithm, COA)作为2023年提出的新型智能…...

Monica 部署指南:自建个人 CRM,记录人际关系的私人助手

Monica 部署指南:自建个人 CRM,记录人际关系的私人助手 Monica 是一个开源的个人 CRM(客户关系管理)工具,但它的目标不是商业客户,而是你生活里真正重要的人——朋友、家人、同事。它帮你记录每个人的生日、联系方式、共同话题、上次见面说了什么,让你成为一个更有心的…...

BetterGI:基于计算机视觉的原神智能辅助工具深度解析

BetterGI:基于计算机视觉的原神智能辅助工具深度解析 【免费下载链接】better-genshin-impact 📦BetterGI 更好的原神 - 自动拾取 | 自动剧情 | 全自动钓鱼(AI) | 全自动七圣召唤 | 自动伐木 | 自动刷本 | 自动采集/挖矿/锄地 | 一条龙 | 全连音游 | 自…...

南派三叔《盗墓笔记》小说1-9卷全txt电子版

《盗墓笔记》是一部由南派三叔创作的长篇探险悬疑小说,讲述了一个普通青年吴邪在偶然得到一本古老笔记后,与经验丰富的盗墓者胖子、神秘莫测的张起灵等人一起踏上探索古墓、追寻秘密的旅程。今天特别为大家整理分享《盗墓笔记》全套9卷,txt电…...

DDrawCompat解决方案:让Windows 11完美运行DirectX 1-7经典游戏

DDrawCompat解决方案:让Windows 11完美运行DirectX 1-7经典游戏 【免费下载链接】DDrawCompat DirectDraw and Direct3D 1-7 compatibility, performance and visual enhancements for Windows Vista, 7, 8, 10 and 11 项目地址: https://gitcode.com/gh_mirrors/…...

百度网盘秒传脚本完整指南:永久文件分享的终极解决方案

百度网盘秒传脚本完整指南:永久文件分享的终极解决方案 【免费下载链接】rapid-upload-userscript-doc 秒传链接提取脚本 - 文档&教程 项目地址: https://gitcode.com/gh_mirrors/ra/rapid-upload-userscript-doc 你是否曾因百度网盘分享链接失效而烦恼&…...

避开这些坑!OpenMV4颜色阈值调试保姆级指南(附Lab颜色空间工具)

OpenMV4颜色阈值调试实战:从Lab空间原理到多环境适配技巧 调试颜色阈值是OpenMV开发中最令人头疼的环节之一。你可能遇到过这种情况:明明在实验室调试完美的色块识别代码,拿到室外就完全失效;或者同一套阈值参数,早上能…...

RTMP视频流的帧格式分析

RTMP(Real-Time Messaging Protocol)是基于 TCP 的协议,其底层传输的数据实际上封装了 FLV(Flash Video)格式的 Tag。在 RTMP 流中,数据被切分成一个个 Chunk(块)进行发送。为了让你…...

ok-ww终极指南:基于图像识别的鸣潮自动化战斗完整解决方案

ok-ww终极指南:基于图像识别的鸣潮自动化战斗完整解决方案 【免费下载链接】ok-wuthering-waves 鸣潮 后台自动战斗 自动刷声骸 一键日常 Automation for Wuthering Waves 项目地址: https://gitcode.com/GitHub_Trending/ok/ok-wuthering-waves 在《鸣潮》这…...

如何永久保存微信聊天记录:终极数据备份与年度报告生成指南

如何永久保存微信聊天记录:终极数据备份与年度报告生成指南 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/…...

杀戮尖塔2mod二次元猎宝

关于《杀戮尖塔2》(Slay the Spire 2)的 “二次元猎宝”(Anime Treasure Hunter)Mod,该作品目前是社区中关注度较高的综合性扩展 Mod。 镜像从夸克下载 1. 作者 该 Mod 通常由 国内 Mod 开发团队/个人“五月&#x…...

5个AI象棋实战技巧:从新手到高手的Vin象棋完全指南

5个AI象棋实战技巧:从新手到高手的Vin象棋完全指南 【免费下载链接】VinXiangQi Xiangqi syncing tool based on Yolov5 / 基于Yolov5的中国象棋连线工具 项目地址: https://gitcode.com/gh_mirrors/vi/VinXiangQi 你是否在象棋对弈中屡战屡败,面…...

2025届必备的AI辅助论文网站推荐

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 针对用户输入特定主题或关键词,AI写作软件能依托先进自然语言处理技术&#xff…...

将 Claude Code 编程助手对接至 Taotoken 的配置指南

将 Claude Code 编程助手对接至 Taotoken 的配置指南 1. 准备工作 在开始配置前,请确保已具备以下条件: 有效的 Taotoken API Key(可在控制台「API 密钥」页面生成)目标模型 ID(可在 Taotoken 模型广场查看 Anthrop…...

Linux(CentOS 6/7)搭建 vsFTPD 服务器及排错实战(SELinux 导致无法切换目录)

环境说明虚拟机系统版本为CentOS 7,IP地址配置为静态IP(如192.168.1.100),确保网络连通性正常。安装 vsFTPD方法一:通过yum安装vsftpd服务:[rootlocalhost Packages]# yum install -y vsftpd验证安装是否成…...

C++版本的opencv速度比gradle版本快5-30倍

结论先说:性能差距非常大!C 版远优于 Gradle 依赖版你用的 implementation org.opencv:opencv:4.9.0 是 OpenCV Java 版,和 C 原生集成 性能差距至少 5~20 倍,实时图像处理(相机、视频)甚至能差 30 倍以上。…...

量子纠缠源同步丢失?C语言底层驱动调试日记(含逻辑分析仪抓取的1.25Gbps QKD时钟域切换波形+源码注释版)

更多请点击: https://intelliparadigm.com 第一章:量子纠缠源同步丢失?C语言底层驱动调试日记(含逻辑分析仪抓取的1.25Gbps QKD时钟域切换波形源码注释版) 凌晨三点十七分,QKD(量子密钥分发&am…...

OpenCore Legacy Patcher:让旧Mac免费升级最新macOS的终极指南

OpenCore Legacy Patcher:让旧Mac免费升级最新macOS的终极指南 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher OpenCore Legacy Patcher是一款革命…...

提高记忆力就能提高成绩是真的吗破解流言 科学认知记忆力与成绩的关系

提高记忆力就能提高成绩是真的吗破解流言的核心结论非常明确:这个说法是片面的流言,记忆力只是影响成绩的众多因素之一,提高记忆力并不必然带来成绩提升,成绩提升是多维度因素共同作用的结果。 提高记忆力就能提高成绩是真的吗 底…...

anlogic pl中断驱动配置

TD工程,一秒给IN5拉高一次电平 设备树而言 / {plint {compatible = "milianke,plint";interrupt-parent = <&gic>;interrupts = <0 82 4>; }; };/ {plint {compatible = "milianke,plint";interrupt-parent = <&gic>;interrup…...

React/Next.js自定义光标库@muybuen/cursor深度实践指南

1. 项目概述&#xff1a;为现代Web应用注入灵魂的交互光标在构建现代Web应用&#xff0c;特别是基于React或Next.js的富交互产品时&#xff0c;我们常常会不自觉地忽略一个最基础却又最直接的交互媒介——鼠标光标。默认的箭头指针千篇一律&#xff0c;它只是系统的一个指示器&…...

三维战场环境下的多无人机智能协同作战系统:基于混合GA-PSO的威胁规避与时间协同路径规划(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

(一区复现)基于强化学习和优化反步法的水面舰艇自适应跟踪控制研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

数据结构协议:跨语言数据一致性的核心解决方案

1. 项目概述&#xff1a;一个数据结构协议的探索最近在翻看一些开源项目时&#xff0c;偶然看到了k-kolomeitsev/data-structure-protocol这个仓库。单看标题&#xff0c;它像是一个关于“数据结构协议”的抽象概念库&#xff0c;但点进去深入探究后&#xff0c;我发现它的核心…...

基于STM32F1实现LADRC线性自抗扰控制(TD、ESO、LSEF编程),以直流电机调速控制为例,支持串口调试,上位机调试

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

2026届学术党必备的AI辅助写作神器实际效果

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 具备智能化解决方案的人工智能论文网站&#xff0c;是为协助学术写作而存在的&#xff0c;它…...

ARMv8调试寄存器详解:断点与观察点控制

1. ARMv8调试寄存器架构概述调试寄存器是现代处理器调试功能的核心硬件组件&#xff0c;它们为开发者提供了在硬件层面监控和干预程序执行流程的能力。在ARMv8架构中&#xff0c;调试寄存器主要分为两大类&#xff1a;断点控制寄存器&#xff08;DBGBCR_EL1&#xff09;和观察点…...

Adafruit Metro RP2350开发板解析与嵌入式开发实践

1. Adafruit Metro RP2350开发板深度解析作为一名长期从事嵌入式开发的工程师&#xff0c;当我第一次看到Adafruit Metro RP2350开发板时&#xff0c;立刻意识到这是一款在兼容性和性能之间取得巧妙平衡的产品。这款开发板最大的亮点在于它采用了Raspberry Pi最新推出的RP2350 …...