三个工具同时跑,一定比一个个跑更好吗?
先把等待时间算清楚
原课给了一个可以直接手算的例子:每次模型生成0.8秒,天气查询1.2秒,日历查询0.9秒,航班查询1.1秒。如果每次只请求一个工具,三个工具之间各插入一次生成,最后再生成回答,总时间为4×0.8+1.2+0.9+1.1=6.4秒。这里暂不计调度和传输额外开销。
若三项查询互不依赖,模型可以一轮提出三个请求,程序并发执行,等最慢的天气查询完成后统一回填,再生成回答。理想时间变成2×0.8+max(1.2,0.9,1.1)=2.8秒。节省的3.6秒来自少两次模型生成和重叠工具等待,不是三个工具各自突然跑得更快。
依赖不是“我觉得这些事情相关”
回到采购:查询价格、查询库存、创建订单。前两个动作都只需要商品名称,可以在适当的资源与权限条件下并发。创建订单却需要知道价格是否在预算内、库存是否足够,并且需要用户授权。它使用前两个动作的结果,因此存在数据或控制依赖。
画图时,箭头表示后一动作必须取得前一动作的某个输出或满足其条件,而不是仅表示讲述顺序。查价格与查库存之间可以没有箭头;它们到下单之间都有箭头。把图按层执行,第一层并行,第二层等所需输入齐全后才启动。
除了数据依赖,还有共享状态冲突。两个动作都不需要对方输出,却可能同时操作同一个浏览器标签页:一个切换到供应商A,另一个切换到供应商B,然后两边都在当前页面点击。它们在概念上独立,在执行资源上却互相干扰。要使用隔离会话、锁或顺序调度,而不是仅看函数参数是否相同。
让相同任务换一种调度
采购动作的正确并行边界
先预测结果,再逐步展开;最后只改变一个条件,找出最早发生分歧的位置。
教学构造场景 · 按下方规则逐步回放;不调用真实模型,不代表实际成功率。
查价3秒、查库存5秒,下单2秒;两查询只读且独立。
- 1. 第一层
同时查价格与库存,等待max(3,5)=5秒。
- 2. 验证
结果齐全后检查库存与预算条件。
- 3. 第二层
条件满足且已获授权,再执行2秒的下单。
同时查价格与库存,等待max(3,5)=5秒。
先预测,再核对结果与原因
理想工具总耗时7秒。并行了独立等待,没有越过下单前提。
再改一个条件,公式要跟着变
如果一个查询被限流,只允许单个请求在运行,理论上的并发分支会排队,时间就不再是最大值。若需要分批发送100个请求,还要考虑并发上限、重试和服务容量。把并发数开得越大,可能造成更多限流与超时,最终有效吞吐反而下降。
如果一个分支失败,能否用其余结果回答取决于任务。查询三家报价可能允许报告“两家已核验、一家失败”;创建订单若要求库存和价格都确认,就不能忽略失败分支继续。等待全部结果、部分结果即可结束、超时后取消,都是需要写清的完成策略。
并行还改变日志阅读方式。完成顺序不再等于请求顺序,因此上一课的调用ID配对变得必要。汇总时保存每个分支的状态、开始与结束时间、返回值和所属请求,才能知道时间花在哪以及缺了哪份证据。只保留一个整体“成功”会掩盖部分失败。
选并行的验收标准应包含正确性与效率两面:固定输入下,结果与串行基线一致;交换返回顺序仍正确;共享资源不会串线;失败分支按规定处理;再比较真实端到端耗时。正确性守住之后,时间差才有意义。
自己解释一次
三个独立工具耗时3、5、4秒,汇总2秒,理想并行多久?
先等待max(3,5,4)=5秒,再汇总2秒,共7秒。串行工具加汇总则为3+5+4+2=14秒。这里没有计入额外模型生成与调度开销。
两个任务无数据依赖,为什么仍可能不能并行?
它们可能共享不可安全并发的状态,例如同一浏览器标签、同一临时文件或受限连接。需要检查资源冲突,而不只检查输入输出。
一个分支超时,是否直接使用其他结果?
取决于成功判据。可部分报告的任务要标明缺失;要求完整前提的动作必须等待恢复或停止。不能为了快速返回而偷偷改变任务要求。
我们已经能调度动作,但工具都返回成功仍不等于任务成功。下一课从环境中的实际结果开始,建立“完成”应该怎样证明的标准。