每次搜索的第一步:Perplexity 如何把嵌入模型的推理开销压到极限 ? Perplexity 的每一个答案,都始于嵌入与排序模型从 EB 级索引中挑出最相关的结果。 Perplexity 拆...
meng shao(@shao__meng) · 人工智能
每次搜索的第一步:Perplexity 如何把嵌入模型的推理开销压到极限 ? Perplexity 的每一个答案,都始于嵌入与排序模型从 EB 级索引中挑出最相关的结果。 Perplexity 拆解了它背后的服务基础设施:当 GPU 计算已趋于最优,加速空间在 GPU 之外,CPU 调度、kernel 启动开销、主机-设备同步、请求路由。团队通过三层架构(Ivy / Tulip / ROSE)加两项关键技术(整模型 CUDA Graph + LazyTensor 异步追踪)来吃掉这些开销,在延迟和吞吐上优于 vLLM v0.22.0。 perplexity.ai/hub/blog/fast-… # 问题定义:嵌入推理的两种流量形态 Perplexity 做了一个很关键的类比,把嵌入推理映射到 LLM 推理的已知模式上: · 批量嵌入(建索引/重索引):大批量长文档,追求最大吞吐以降低成本。计算特征等同于 LLM 的 Prefill 阶段,属于算力受限(compute-bound)。 · 重排打分(向量检索之后):中等批量,需要在吞吐与延迟之间取得平衡。同样对应 Prefill,瓶颈介于算力与带宽之间。 · 在线嵌入(用户查询):只有几个 token,追求最低延迟。计算特征等同于 LLM 的 Decode 阶段,属于显存带宽受限(memory-bound)。 这个映射的工程意义在于:他们不需要为嵌入模型单独写一套 kernel。LLM 服务栈里已经调优过的 prefill 和 decode kernel 可以直接复用,pplx-embed 和 Qwen3.5 的 LLM decoding 走的是同一套 kernel。 # 三层架构:Ivy → Tulip → ROSE Ivy(Rust HTTP 网关) 负责所有 CPU 侧预处理:JSON 解析、分词、输入模板、批次切分,再转成自定义 gRPC 协议发给下游。把这些从推理实例剥离出来的好处是,分词和格式化参数可以独立调整,不用碰昂贵的 GPU 实例。Ivy 还承担负载均衡:把大批量请求切块分发到多个副本,避免单个副本被大请求压垮。另外他们自研的 unigram 分词器已全量上线,对延迟改善显著(这是另一篇博文的内容)。 Tulip(Rust gRPC 推理服务器) 基于 tokio + tonic,做调度和批处理。调度策略刻意做得极简:先来先服务,请求在 GPU 忙时自然累积,空闲时打包发出。 这个"简单"是有理论依据的。他们观察到:对小型嵌入模型、在实际服务的序列长度下,dense 层的线性开销主导,attention 的二次开销可以忽略。所以延迟基本与 token 总数成正比,与序列数无关。一旦批次达到约 512 token(十亿参数以下的模型),GPU 就已饱和,再塞更多序列没有收益。既然如此,复杂的调度算法带来的边际价值就很小。 ROSE(Runtime-Optimized Serving Engine,Python) 真正的模型实现层,定义 kernel、层、模型结构、前向传播和 CUDA Graph 管理。它原本为 LLM 服务而建,通过一个 step() 函数与 Tulip 桥接——接收一个 batch,返回一个指向 GPU 上计算结果的引用(而非结果本身,这点后面很关键)。 嵌入模型与 LLM 的差异被限定在 attention 层:嵌入不需要 KV cache,改用支持 ragged(变长非填充)输入的 attention kernel 变体,避免 padding 浪费。dense 层则完全一致,因为 token 向量本来就是独立处理的。 # 核心技术一:整模型 CUDA Graph + 惰性捕获 为什么需要? 一次前向传播是 CPU 与 GPU 的交替配合:CPU 负责调度和 kernel 启动,GPU 负责矩阵乘法、attention、norm、激活。大批量时 GPU 执行时间长,CPU 开销可忽略;但小批量时,Python/PyTorch 的 kernel 启动开销会反过来超过 GPU 实际计算时间。嵌入模型本身很小,这个"拐点"来得很早——文中说在数千 token、几十个序列的批次规模上 CPU 开销才被 GPU 时间盖过。也就是说,在线查询这种几十 token 的请求,绝大部分时间在等 CPU。 做法 CUDA Graph 把整个前向传播的所有 kernel 启动元数据一次性捕获,之后一次驱动调用即可回放,跳过所有 Python 代码。Perplexity 为所有嵌入模型构建整模型级别的图。有些 attention 实现依赖主机侧动态输入来配置 kernel 启动,会破坏图捕获,他们把修复上游到了相关 kernel 库。 代价与缓解 CUDA Gra