# ⚙️ LLM Compiler论文解读:并行函数调用的编译器思维(2023)
⚙️ LLM Compiler论文解读:并行函数调用的编译器思维
论文信息
标题:An LLM Compiler for Parallel Function Calling
作者:Sehoon Kim, Suhong Moon, Ryan Tabrizi等(Berkeley团队)
发表:ICML 2024
arXiv:2312.04511
提交日期:2023年12月7日 | 最终版本:2024年6月5日
速查表:LLM Compiler核心要点
| 维度 | 核心内容 |
|---|---|
| 核心创新 | 借鉴编译器设计,实现Agent函数调用的并行执行 |
| 解决痛点 | 串行函数调用导致的高延迟、高成本、低效率 |
| 技术架构 | Planner(规划) + Task Fetching Unit(调度) + Executor(并行执行) |
| 性能提升 | 延迟加速3.7x,成本节省6.7x,准确率提升9% |
| 关键洞察 | "像编译器一样思考:先规划,再并行执行" |
| 历史地位 | Agent系统性能优化的关键技术,开启并行Agent时代 |
历史演进:从串行到并行的Agent执行
时间线关键节点
2022-2023: Agent/工具调用时代开启
↓
问题:Agent需要串行调用多个函数
↓
例子:ReAct方法(Reasoning + Acting)
↓
性能瓶颈:延迟高、成本高
↓
2023年12月: LLM Compiler提出并行执行
↓
核心突破:借鉴编译器设计,并行调用函数
↓
2024年6月: ICML正式发表
技术背景:Agent时代的效率困境
传统Agent执行的痛点:
1. 串行执行的低效性
ReAct方法的问题:
# 传统Agent执行流程
user_query = "查询北京今天的天气,然后发邮件给我"
# Step 1: Think(思考)
model.call("需要调用天气查询API")
# Step 2: Act(执行函数)
weather_result = weather_api.get_weather("北京")
# Step 3: Observe(观察结果)
model.call(f"天气是{weather_result}")
# Step 4: Think(再次思考)
model.call("需要发送邮件")
# Step 5: Act(执行函数)
email_api.send_email(content=weather_result)
# 问题:
# - 必须等待Step 1完成才能做Step 2
# - 每个步骤都要等待上一个完成
# - 总延迟 = sum(所有步骤延迟)
LLM Compiler的并行执行:
# 并行Agent执行流程
user_query = "查询北京今天的天气,然后发邮件给我"
# 1. Planner(规划)
execution_plan = llm.compiler.plan(user_query)
# 输出:并行调用 [weather_api, email_api]
# 2. Executor(并行执行)
results = llm.compiler.execute_parallel([
weather_api.get_weather("北京"),
email_api.prepare_template() # 可以提前准备
])
# 总延迟 = max(函数调用延迟)
# 性能提升:3.7x
2. 成本问题
串行执行的成本:
每次思考都需要调用LLM
N个函数调用 → N次Think → N次LLM调用
示例:3个函数
- Think 1: 0.5秒,$0.01
- Act 1: 0.2秒,$0
- Think 2: 0.5秒,$0.01
- Act 2: 0.2秒,$0
- Think 3: 0.5秒,$0.01
- Act 3: 0.2秒,$0
总时间:1.6秒
总成本:$0.03
并行执行的成本:
规划:1次LLM调用
执行:并行调用所有函数
- Plan: 0.5秒,$0.01
- Execute 1,2,3 in parallel: 0.2秒,$0
总时间:0.7秒(↓56%)
总成本:$0.01(↓67%)
3. 准确性问题的根源
串行执行导致的信息缺失:
Problem:
- 函数A需要的信息,函数B刚好有
- 但串行执行时,B还没执行完
- A基于部分信息做出决策
Result:
- 决策可能不准确
- 需要多次迭代修正
并行执行的信息完整性:
Solution:
- 所有函数并行执行
- 获得完整上下文
- 一次性做出正确决策
Result:
- 准确率提升9%
️ 设计哲学:编译器思维的应用
核心设计思想
1. 编译器架构的借鉴
经典编译器设计:
源代码
↓
词法分析(Lexical Analysis)
↓
语法分析(Parsing)
↓
语义分析(Semantic Analysis)
↓
中间代码生成(Code Generation)
↓
优化(Optimization)
↓
并行代码调度(Task Scheduling)
↓
机器码执行(Execution)
LLM Compiler的映射:
用户查询(Natural Language)
↓
Function Calling Planner(规划)
↓
Task Fetching Unit(调度)
↓
Executor(并行执行)
↓
整合结果(Result Aggregation)
设计洞察:
"Agent函数调用系统,本质上和编译器一样:
都是在做'规划-调度-执行'的工作,
为什么不能像编译器一样优化执行?"
2. 并行性的识别与利用
编译器中的并行优化:
// 经典编译器并行优化示例
for (i = 0; i < n; i++) {
a[i] = b[i] + c[i]; // 可以并行
d[i] = e[i] * f[i]; // 可以并行
}
LLM Compiler中的并行识别:
问题:如何识别哪些函数可以并行执行?
答案:基于函数依赖关系
独立函数(Independent):
- 函数A的结果不影响函数B
- → 可以并行执行
依赖函数(Dependent):
- 函数A的输出是函数B的输入
- → 必须串行执行
3. 三阶段设计:Planner-Task-Executor
Stage 1: Function Calling Planner
职责:分析用户查询,生成执行计划
输入:用户查询 + 可用函数列表
输出:执行计划(依赖图)
类似编译器的:
- 词法分析:识别需要哪些函数
- 语法分析:确定函数调用顺序
- 依赖分析:构建依赖图
Stage 2: Task Fetching Unit
职责:根据依赖图,调度任务执行
算法:Topological Sort(拓扑排序)
- 识别可并行执行的任务集合
- 动态调度任务
类似编译器的:
- 并行代码调度
- 任务队列管理
Stage 3: Executor
职责:并行执行独立的函数调用
实现:多线程/异步执行
- 同时调用多个函数
- 收集结果
- 整合输出
类似编译器的:
- 并行代码执行
- 结果聚合
思维路线梗概
问题定义
如何在Agent系统中高效地执行多个函数调用,
同时保证准确性并降低成本和延迟?
解决方案构建路径
Step 1: 识别串行执行的瓶颈
观察:ReAct等方法的串行执行
Think → Act → Observe → Think → Act → ...
问题:
- 延迟:累加的Think时间
- 成本:多次LLM调用
- 效率:无法利用并行性
Step 2: 借鉴编译器设计
洞察:编译器是如何优化的?
- 分析依赖关系
- 识别并行性
- 生成并行代码
应用:Agent系统也可以这样做!
Step 3: 设计三阶段架构
1. Planner:规划阶段
- 理解用户意图
- 识别需要的函数
- 构建依赖图
2. Task Fetching Unit:调度阶段
- 分析依赖关系
- 识别可并行任务
- 动态调度
3. Executor:执行阶段
- 并行调用独立函数
- 收集结果
- 整合输出
Step 4: 实现优化策略
优化技术:
- 依赖图构建
- 拓扑排序
- 动态调度
- 结果缓存
核心因果关系
串行执行导致高延迟
↓
需要识别并行性
↓
借鉴编译器设计思想
↓
三阶段架构:规划-调度-执行
↓
并行执行独立函数
↓
延迟加速3.7x,成本节省6.7x
技术深度解析
架构设计
完整执行流程
┌─────────────────────────────────────────────────┐
│ LLM Compiler执行流程 │
└─────────────────────────────────────────────────┘
User Query: "查询天气并发送邮件"
↓
┌──────────────┐
│ Planner │ 分析查询,生成执行计划
└──────────────┘
↓
Execution Plan:
{functions: [weather_api, email_api],
dependencies: {} # 无依赖,可并行
}
↓
┌──────────────┐
│Task Fetching │ 识别可并行任务
└──────────────┘
↓
Parallel Tasks:
- Task 1: weather_api → "北京今天晴天"
- Task 2: email_api → 准备模板
↓
┌──────────────┐
│ Executor │ 并行执行
└──────────────┘
↓
Integration → Final Result
Planner设计
# 伪代码:Function Calling Planner
class FunctionCallingPlanner:
def __init__(self, llm, available_functions):
self.llm = llm
self.functions = available_functions
def plan(self, user_query):
# 识别需要的函数
prompt = f"""
用户查询:{user_query}
可用函数:{self.functions}
请生成执行计划,包括:
1. 需要调用的函数列表
2. 函数之间的依赖关系
输出格式:
{{
"functions": [
{"name": "weather_api", "args": {...}},
{"name": "email_api", "args": {...}}
],
"dependencies": []
}}
"""
# LLM生成计划
plan = self.llm.generate(prompt)
return self.parse_plan(plan)
Task Fetching Unit设计
# 伪代码:Task Fetching Unit
class TaskFetchingUnit:
def __init__(self):
self.task_queue = []
self.executing = set()
def schedule_tasks(self, execution_plan):
# 构建依赖图
graph = self.build_dependency_graph(execution_plan)
# 拓扑排序
schedule = self.topological_sort(graph)
return schedule
def build_dependency_graph(self, plan):
graph = {}
for function in plan['functions']:
graph[function['name']] = []
# 找出依赖
for dep in plan['dependencies']:
if dep['target'] == function['name']:
graph[function['name']].append(dep['source'])
return graph
def topological_sort(self, graph):
# 经典拓扑排序算法
# 找出所有没有依赖的任务
ready_tasks = [task for task, deps in graph.items() if not deps]
schedule = []
while ready_tasks:
# 当前可以执行的任务(可并行)
current_parallel_tasks = ready_tasks
ready_tasks = []
for task in current_parallel_tasks:
schedule.append(task)
# 更新其他任务的依赖
for other_task, deps in graph.items():
if task in deps:
deps.remove(task)
if not deps and other_task not in schedule:
ready_tasks.append(other_task)
return schedule
Executor设计
# 伪代码:Executor
class Executor:
def __init__(self):
self.function_registry = {}
def execute_parallel(self, tasks):
# 并行执行任务
results = {}
# 使用线程池或异步执行
import concurrent.futures
with concurrent.futures.ThreadPoolExecutor() as executor:
futures = {}
for task in tasks:
future = executor.submit(self._execute_task, task)
futures[task['name']] = future
# 收集结果
for task_name, future in futures.items():
results[task_name] = future.result()
return results
def _execute_task(self, task):
func = self.function_registry[task['name']]
return func(**task['args'])
优化技术
1. Dependency Graph构建
静态分析:
分析函数签名,识别依赖:
- 函数A的输出 → 函数B的输入:B依赖A
- 无共享参数:独立执行
例子:
weather_api() → 输出:weather_data
email_api(weather_data) → 依赖weather_data
→ email_api必须等待weather_api
动态分析:
运行时识别依赖:
- LLM判断任务是否可以并行
- 基于上下文,动态调整依赖关系
2. Topological Sort调度
算法:
1. 构建依赖图
2. 找出所有入度为0的节点(无依赖)
3. 同时执行这些节点(并行)
4. 移除已完成的节点
5. 重复直到所有节点完成
示例:
依赖图:
Task A (无依赖)
Task B (无依赖)
Task C (依赖A)
Task D (依赖A, B)
调度结果:
Epoch 1: [A, B] # 并行执行
Epoch 2: [C, D] # 并行执行
3. 结果缓存与重用
Cache策略:
缓存机制:
- 相同的函数调用可以重用结果
- 减少重复计算
例子:
"查询北京天气" → 缓存5分钟
后续请求直接返回缓存结果
实验结果与影响
性能突破
延迟加速:
数据集:多种Agent任务
ReAct方法:
- 平均延迟:10.5秒
- 函数调用数:5个
- 串行执行
LLM Compiler:
- 平均延迟:2.8秒
- 并行执行
- 加速比:3.7x
成本节省:
成本分析:
- ReAct:多次LLM调用
- LLM Compiler:规划 + 并行执行
成本对比:
ReAct: $0.05/query
LLM Compiler: $0.015/query
节省:67%(6.7x改进)
准确率提升:
性能对比:
ReAct: 82% 准确率
LLM Compiler: 91% 准确率
提升:9%
原因:
- 并行执行获得完整上下文
- 一次性决策更准确
- 减少了信息不完整导致的错误
与基线方法对比
| 方法 | 延迟 | 成本 | 准确率 | 并行性 |
|---|---|---|---|---|
| ReAct | 基准 | 基准 | 82% | 无 |
| LLM Compiler | 3.7x加速 | 6.7x节省 | 91% | ✅ |
| AutoGPT | 中等 | 高 | 85% | 有限 |
批判性思考
论文的局限性(2025视角)
1. 依赖分析的准确性
论文假设:可以准确识别函数依赖
实际情况:
- ❌ 复杂场景下的依赖关系难以静态分析
- ❌ LLM规划的依赖可能不准确
- ❌ 需要运行时验证
改进方向:
- 动态依赖检测
- 回滚机制(如果依赖判断错误)
2. 函数调用的原子性问题
问题:假设函数调用是原子的
实际情况:
复杂函数可能包含多个子步骤:
email_api() →
├─ 准备模板
├─ 填充内容
├─ 发送
└─ 确认发送
如果中间步骤失败怎么办?
现实挑战:
- 并行执行难以处理部分失败
- 需要更复杂的错误处理机制
3. 同步与异步的权衡
论文侧重:并行执行
未充分讨论:
- ❌ 异步执行的复杂性
- ❌ 超时处理
- ❌ 负载均衡
4. 函数依赖的循环检测
论文:假设依赖图是DAG
实际问题:
可能存在隐式循环:
Task A → Task B → Task A
需要循环检测机制
与现代技术的对比(2025视角)
| 维度 | LLM Compiler | 现代实践 |
|---|---|---|
| 并行度 | 中等 | 高(多进程+多GPU) |
| 依赖分析 | LLM规划 | 静态+动态分析 |
| 错误处理 | 基础 | 容错+重试机制 |
| 扩展性 | 中等 | 分布式执行 |
核心洞察与价值
对技术决策的启示
1. 编译器思维的跨领域应用
LLM Compiler的启示:
"编译器优化的思想
可以应用到任何需要调度和优化的系统"
应用场景:
- Agent函数调用(本文)
- RAG系统(文档调度)
- Multi-Agent协作(任务分配)
2. 并行的价值巨大
关键洞察:
"在Agent系统中,并行性带来的收益:
- 延迟加速:3-4x
- 成本节省:6-7x
- 准确率提升:~10%
这是一个多赢的局面。"
3. 规划-执行分离的设计模式
设计哲学:
分离关注点:
- Planner:负责"What to do"(做什么)
- Executor:负责"How to do"(怎么做)
好处:
- 可优化执行路径
- 易于维护和扩展
- 符合单一职责原则
对Agent实践的启示
1. Agent系统的性能优化路径
优化层次:
Level 1: Prompt优化(LLMLingua)
↓
Level 2: 并行执行(LLM Compiler)
↓
Level 3: Agent协作优化
↓
Level 4: 系统级优化
LLM Compiler定位:
- Level 2的优化技术
- 承上启下的关键环节
2. 与RAG系统的互补
角色分工:
RAG系统:
- 外部知识检索
- 向量数据库
- 文档压缩
LLM Compiler:
- Agent函数调用
- 并行执行
- 资源调度
组合应用:
用户查询
→ RAG检索相关文档
→ LLM Compiler并行调用多个函数
→ 整合结果
历史影响与遗产
对Agent领域的贡献
1. 开启Agent性能优化时代
Before LLM Compiler:
Agent = 串行执行
性能:慢、贵、效率低
After LLM Compiler:
Agent = 并行执行
性能:快、便宜、效率高
2. 编译器思维的推广
影响范围:
- Agent系统设计
- Multi-Agent协作
- RAG系统优化
- 系统架构设计
3. 启发后续研究
相关改进:
- FrugalGPT (2023):模型调用优化
- GPT-FrugalGPT协作 (2024):多模型协作
- 推理服务优化:延迟优化
当前应用(2025)
实际应用场景:
- ✅ LangChain集成LLM Compiler思想
- ✅ AutoGPT等系统采用并行执行
- ✅ 企业Agent系统优化
- ✅ 开源项目活跃
行业采用:
工具支持:
- LangChain: Parallel Agent
- AutoGPT: Multi-step execution
- 各种Agent框架
实践案例:
- AI助手并行执行多个工具
- 数据分析Agent并行查询
- 代码生成Agent并行调用
行动建议
如果你是...
学生/研究者:
- ✅ 完整阅读论文(ICML 2024)
- ✅ 理解编译器设计思想
- ✅ 实现简化版LLM Compiler
- ✅ 思考扩展到其他系统
工程师/开发者:
- ✅ 评估Agent系统的性能瓶颈
- ✅ 实现函数调用的并行执行
- ✅ 优化依赖分析算法
- ✅ 监控性能提升
决策者/架构师:
- ✅ 评估并行执行的ROI
- ✅ 设计Agent系统的架构
- ✅ 考虑可扩展性
- ✅ 制定性能优化策略
延伸阅读与资源
相关论文
-
ReAct (2022):串行Agent执行
- arXiv: 2210.03629
-
AutoGPT (2023):自主Agent系统
- GitHub: AutoGPT
-
FrugalGPT (2023):LLM调用优化
- arXiv: 2304.02875
实践资源
代码实现:
- GitHub: LLM Compiler
- LangChain Parallel Agent
- AutoGPT
评估工具:
- AgentBench
- Agent测试套件
总结:LLM Compiler的历史地位
为什么这篇论文重要?
1. 性能优化的关键突破
解决了Agent系统的核心痛点
延迟加速3.7x
成本节省6.7x
2. 设计范式的创新
引入编译器思维
规划-调度-执行分离
启发了后续研究
3. 工程实践价值大
可直接应用于生产环境
多种Agent系统集成
行业广泛采用
对2025年的意义
Agent系统必备知识:
- 理解并行执行的价值
- 掌握编译器思想的应用
- 设计高效的Agent架构
技术趋势:
从串行到并行
从单Agent到Multi-Agent
从线性到图状执行
创建时间:2025年1月
作者:基于Berkeley团队论文的深度解读
推荐阅读时长:40-50分钟
学习检查清单:

浙公网安备 33010602011771号