我最近刚完成了一份推荐系统 Scaling Up 技术路线的调研,起因很简单:线上的推荐服务用户量涨了三倍,特征数量翻了两番,模型训练从一晚上变成三天,在线召回开始出现明显的超时,离线实验排队排到第二天。这不是某个环节出了问题,而是整条链路都在逼近单机、单卡的物理上限。于是我把调研拆成数据、模型、服务三条线,把主流路线挨个过了一遍,最后沉淀了一份能直接指导选型的结论。这篇文章就是想给同样在“系统快撑不住”边缘徘徊的同行一个参考,尤其是那些正在做技术选型、需要向团队输出路线文档的人。文章里不涉及任何公司内部方案,全是可以公开复现的技术路线与工程判断;哪怕你只是在 Ubuntu 上搭过电影推荐系统做练习,也能理解这些大型方案到底在解决什么问题。
先说一个整体判断:Scaling Up 不是一个独立的技术点,而是一整套从训练、特征、模型到在线服务的连锁改造。很多人以为它等于“换个更大的模型”,实际上业务规模不涨到一定阈值,花大力气上分布式完全是浪费;而一旦到了阈值,缺的不只是算力,还有数据管线、参数分发、检索结构这些配套工程。所以调研的核心任务不是选一个框架,而是判断你的系统在哪个环节先撑不住,再决定走哪条路线。
1. 推荐系统为什么走到 Scaling Up 这道坎上
我见过太多团队把 Scaling Up 当作模型层面的事情:模型不够准,就把网络加宽、加深,堆更多参数。但真实业务里,触发大规模改造的往往不是模型效果,而是系统表现出了三个很明确的临界信号。
1.1 三个临界信号:训练变慢、特征放不下、召回扛不住
第一个信号是训练时长失控。全量样本的训练周期从小时级变成天级,意味着实验迭代节奏完全被打乱。算法同学改一个特征、调一个 Loss,都得等两天才能看到结果,这已经不是“慢”的问题,而是整个团队的产出效率被拖死。第二个信号是特征与 Embedding 表放不进单机内存。推荐系统里大量使用 ID 类稀疏特征,用户 ID、物品 ID、标签、上下文,每张特征表都要维护一份 Embedding 向量。用户量一旦过亿,物品量过千万,Embedding 表轻轻松松几十 GB 甚至上百 GB,单卡放不下,单机内存也紧张。第三个信号是在线召回扛不住流量。候选物品集变大之后,召回阶段要扫的集合膨胀,向量相似度计算的耗时跟着上去,QPS 稍微一冲,P99 延迟就突破预算。
这三个信号是关键,因为它们标志着朴素优化已经到了头。特征筛选、样本过滤、模型精简这些做法还能再挤一点空间,但系统的物理上限摆在那里:单机 CPU 核数、内存带宽、GPU 显存都是固定的,再怎么调都绕不过去。
1.2 Scaling Up 与 Scale Out:两个方向的取舍
调研里有个概念必须先澄清:Scaling Up 和 Scale Out 不是一回事。Scaling Up 原本指垂直扩展,比如换更强的 CPU、更大的内存、更高级的 GPU;Scale Out 是水平扩展,加机器、加节点、把负载摊开。但在推荐系统的业界的语境里,Scaling Up 技术路线通常是把两者结合起来:一边把模型参数量往上提,一边把分布式工程能力补上。
这里容易产生一个误区:认为规模化就是把所有东西全部拆成分布式。实际上有很多场景根本不需要走那么重。比如你只是做一个基于 Ubuntu 的电影推荐系统练手,单机跑 Python 模型完全够;但如果你负责的是一个千万级日活的视频平台,同样的算法就不得不拆成分布式样本管线、参数服务器和向量检索集群。调研的第一件事,其实是确定自己到底在哪个区间,再去谈技术路线。
2. Scaling Up 到底在扩什么:四个维度的拆解
推荐系统做规模化,表面上看是“数据变多、模型变大”,拆开看其实是四个维度的瓶颈同时出现,任何单一维度的优化都无法解决整体问题。
| 扩展维度 | 典型瓶颈表现 | 规模化手段 | 主要代价 |
|---|---|---|---|
| 样本与特征 | 数据加载慢、特征拼接耗时长 | 分布式存储、特征实时管线 | 研发复杂度上升 |
| 模型参数 | Embedding 表撑爆显存 | 参数分区、压缩、稀疏化 | 精度损失或同步一致性变难 |
| 训练吞吐 | 单卡训练周期过长 | 数据并行、模型并行、混合并行 | 通信开销增加 |
| 在线服务 | QPS 上不去、时延抖动 | 模型分片、缓存、向量检索 | 一致性与成本权衡 |
2.1 样本与特征:最容易被低估的第一道坎
我调研时发现,很多团队第一反应是上分布式训练框架,结果最后卡住他们的是数据管线的吞吐。推荐系统的训练样本不是简单的一行行文本,而是包含用户侧、物品侧、上下文侧的多路特征拼接。样本量从几千万涨到几十亿之后,单机 IO 和特征拼接流程会直接成为瓶颈。你训练脚本写得再快,数据喂不进来也是白搭。
这个维度上的 Scaling Up 主要靠两件事:一是把样本存储从本地文件挪到分布式文件系统(比如 HDFS 或云上对象存储),让多机可以并行读取;二是把特征计算离线化、预聚合,避免训练时临时算特征。很多人忽略了第二点,觉得特征计算是小事,实际上在超大样本量下,特征拼接的开销往往比模型前向计算还大。
2.2 模型参数量:Embedding 表才是真正的大头
推荐模型里最吃参数的不是神经网络部分,而是 Embedding 表。原因很简单:神经网络层数再深,参数也就是千万到亿级别;而一张覆盖全量用户或全量物品的 Embedding 表,参数量等于 ID 数量乘以 Embedding 维度。简单算一笔账:1 亿个物品 ID,每个 ID 用 64 维向量表示,按 4 字节浮点计算,就是 1 亿 × 64 × 4 字节,约 25.6 GB。如果用户侧、标签侧再有几张同样规模的特征表,几十张表叠起来,几百 GB 的内存开销并不夸张。
所以模型维度的 Scaling Up 本质上是在回答一个问题:这几百 GB 的参数,怎么存、怎么更新、怎么在训练时高效读写?这直接决定了你需要走参数服务器路线,还是先做一轮 Embedding 压缩来推迟分布式的引入。
2.3 训练吞吐:从单卡到集群不是简单加机器
训练侧要扩的不只是存储,还有算力。单卡 GPU 显存有限,即使装得下模型,训练一个 epoch 的时间也可能从几小时变成几天。分布式训练成了必然选项,但加机器不等于线性加速:数据并行之下,每张卡都要维护完整模型副本,Embedding 表太大时根本塞不进显存;模型并行又要切分网络层,通信开销很容易吃掉计算收益;更麻烦的是稀疏特征场景,Embedding 的动态更新需要跨节点同步,这时候就得引入参数服务器或者类似 AllReduce 之外的模式。
2.4 在线服务:时延约束才是真正的分水岭
离线训练可以接受一个训练任务跑几个小时,在线推理可不行。线上推荐接口通常要求 P99 延迟在几十毫秒量级,QPS 是训练端的几十倍甚至上百倍。于是 Scaling Up 到服务端之后,问题变了:模型参数分布到多机,特征获取要跨网络,向量检索要在毫秒级别返回 TopK 结果,这些约束离线训练时根本感知不到。
这也是调研里最容易跑偏的地方。很多人把精力全放在训练框架上,忽略了服务端的模型分片与检索架构,结果模型是能训练了,却没法上线。真正完整的 Scaling Up 路线,一定是从样本到训练再到推理全链路一起设计的。
3. 主流技术路线对比:分布式训练、压缩稀疏化、两级检索
把四个维度拆完之后,整体路线也就清晰了。从我调研到的公开资料和社区实践看,目前的技术路线大致可以分成三条:分布式训练、Embedding 压缩与特征稀疏化、召回-排序两级体系加上向量检索。它们不是互斥的,实际落地时往往按阶段叠加。
3.1 路线A:分布式训练,从数据并行到混合并行
分布式训练是最“正统”的 Scaling Up 路线,解决的是模型参数和训练吞吐的瓶颈。这条路线内部又分成好几个层次:
- 第一层是数据并行,比如 PyTorch DDP。每张卡上放完整模型,数据切片后多卡同时算,梯度做 AllReduce 同步。这种方式实现简单,适合模型参数能塞进单卡显存的中等规模场景。
- 第二层是参数服务器模式,专门应对稀疏超大模型。参数被拆分到多台 PS 节点上,Worker 节点负责计算梯度,只和 PS 通信拉取自己需要的参数。CTR 预估场景里非常常见。
- 第三层是混合并行,把 Dense 参数放 GPU,Sparse Embedding 放 CPU 或 PS,结合流水线并行进一步扩大可训练规模。DeepSpeed、Horovod、TensorFlow Distribution Strategy 这些框架基本都支持这种组合。
这里给一个最基础的 PyTorch DDP 启动示例,让大家对成本有个概念:
# 单机多卡数据并行 torchrun --nproc_per_node=8 train.py --batch_size=65536但要注意,数据并行只是入门的规模化手段。一旦 Embedding 表超过几十 GB,DDP 就撑不住了,因为每张卡都要有一份完整的参数副本,显存直接爆掉。这时候才需要往上走参数服务器或混合并行。
3.2 路线B:Embedding 压缩与特征稀疏化,性价比最高的前置动作
我调研时有个很强烈的感受:很多系统其实还远没到必须上分布式的地步,只是参数管理太粗糙。先用压缩手段把参数规模降下来,往往能推迟甚至省掉一次大规模架构改造。
Embedding 压缩的手段不少。常用的是 Hash Trick,把海量 ID 通过哈希映射到固定大小的 Embedding 池,存储上限可控,缺点是不同 ID 可能冲突。其次是频率截断,把出现次数过低的 ID 直接映射到一个共享的 OOV 向量,低频长尾是推荐数据里的大头,截断之后参数规模能缩小一个数量级。再往上还有维度裁剪、INT8 量化、低秩分解这些方法,都能在尽量不伤效果的前提下压缩参数体积。
这条路线之所以重要,是因为它和分布式训练可以叠加。先压缩到单机能放下的程度,就能继续用简单的方式训练;即使将来一定要上分布式,参数变小之后通信开销也小很多,系统更稳。
3.3 路线C:召回-排序两级体系与向量检索,解决候选集爆炸
第三路线和前面两条相互独立,它针对的是服务端和系统架构层面的规模膨胀。当物品规模达到千万、亿级,精排模型不可能对全量物品逐个打分,硬算的时间复杂度和算力成本都不可接受。业界普遍把系统拆成召回、粗排、精排两级或三级漏斗:召回阶段先用轻量模型从全量候选中筛出几百上千个,精排再对这批小候选做复杂模型的打分排序。
召回阶段的爆发点就是向量检索。把用户和物品都用模型映射成向量,召回就变成了在超大向量集合里找最近邻。这就绕不开 Faiss、HNSW 这些向量检索引擎。一个典型的建索引流程大概是:
import faiss # 假设 item_vectors 是从模型里取出的物品向量,维度 d index = faiss.IndexFlatIP(d) # 内积召回 index.add(item_vectors) # 全量物品入库 D, I = index.search(user_vector, k) # 返回 TopK 物品 ID不过 Faiss 单机索引在数据量非常大时也需要分片和分布式部署,所以现在大型系统基本都演进到了分布式向量检索集群,配合 ANN 索引算法把单次查询延迟控制在毫秒级。
三条路线的适用边界可以这样对照:
| 技术路线 | 针对瓶颈 | 上手成本 | 典型适用阶段 |
|---|---|---|---|
| 分布式训练 | 参数超单机、训练周期过长 | 高 | 亿级样本、超大 Embedding |
| Embedding 压缩 | 参数体积、显存压力 | 低 | 所有规模化前期 |
| 两级检索与向量召回 | 候选集爆炸、在线时延 | 中 | 千万级物品以上 |
4. 选型的判断依据:别用短视频的架构去做电影推荐
调研工作做到最后,最难的不是了解技术本身,而是决定自己该用哪一套。我从实践里抽出的判断逻辑非常简单:先把数字摆出来,再决定路线,而不是根据行业热点选型。
4.1 先量化再选型
我建议在调研一开始就拉一张表,把下面这些指标填清楚:日均活跃用户数、物品总量、单用户平均行为数、特征总数、Embedding 总参数体积、单日样本规模、目标训练周期、在线峰值 QPS 和延迟预算。这些数字填完,路线基本就浮出水面了。
举个例子,如果物品量只有几十万,用户量百万级,Embedding 总参数不超过 10 GB,那么老老实实做特征工程和模型优化就够了,上参数服务器纯属给自己找麻烦。反过来说,如果单日样本已经到几十亿,Embedding 表超 100 GB,训练周期超过一周,那就不是“要不要上分布式”的问题,而是“怎么把分布式做稳”的问题。
4.2 不同量级的推荐路线对照
| 业务量级 | 典型场景 | 推荐路线 |
|---|---|---|
| 百万级用户、千万级样本 | 中小型产品、垂直社区 | 单机训练 + Embedding 压缩 + 简单召回 |
| 千万级用户、亿级样本 | 成长期内容平台 | 数据并行 + 特征管线改造 + Faiss 向量召回 |
| 亿级用户、百亿级样本 | 头部平台 | 混合并行 + 参数服务器 + 分布式向量检索 |
这里要特别提醒一点:量级不是唯一的判断依据,还要看特征结构和业务形态。同样是千万级用户,电商的不仅是特征跨多个实体、更新频繁,而且非常依赖实时特征计算,对数据管线的要求远高于一个电影社区。反过来,电影推荐系统的商品数相对固定,特征稳定,Scaling Up 的迫切性天然低很多。所以我在调研结论里反复强调一个观点:方案要跟着业务特性走,不能看见别人用短视频的架构就觉得自己的电影推荐系统也得上整套分布式。
4.3 技术栈的补充判断
除了路线本身,技术栈的选择也会影响推进速度。Python 是整个推荐系统调研与模型实验阶段最高效的技术路线,绝大多数团队都会先用 Python 把样本处理、模型训练、召回验证跑通,再决定是否对生产环节做工程化改造。图像或视频类特征进来之后,视觉建模的主流技术路线上已经跑到了 ViT 这套体系,多模态推荐系统需要考虑这部分额外的计算开销,这也会反过来影响你对算力规模的判断。至于环境部署,在 Debian/Ubuntu 这类服务器上安装 Faiss、Redis、Kafka 等开源组件都相当顺滑,调研阶段的实验环境搭建成本通常不需要担心。
5. 调研阶段最容易踩的坑与我的实操建议
做完这份调研,我发现真正让团队卡壳的往往不是技术本身,而是几个反复出现的工程认知误区。写在这里,希望大家少走点弯路。
5.1 坑一:只算模型算力,不算特征工程开销
我见过一个方案,模型层做得非常完整,混合并行、参数服务器都规划好了,结果一压测发现特征拼接环节 CPU 先被打满,训练集群根本跑不满。推荐系统的数据流里,特征不是天然就排好队等模型的,它要经过采集、清洗、拼接、分发,这个链路的吞吐往往比模型前向计算更容易成为瓶颈。做规模化预算时,一定要把特征管线的 CPU 开销和 IO 开销算进去,否则上线后发现瓶颈不在 GPU 而在 CPU,会非常被动。
5.2 坑二:拿离线训练吞吐倒推在线服务能力
这是另一个常见偏差。有人觉得离线训练做到了一天处理 10 亿样本,线上处理 1000 万请求肯定没问题。实际上离线训练可以批量、异步、失败重试,在线推理却要在毫秒级内完成并且不能有抖动。在线侧要额外考虑特征获取的 RTT、模型分片的通信、向量检索的召回率与延迟权衡。我的建议是离线、在线分开做容量评估,不要互相倒推。
5.3 坑三:忽略数据回放与一致性成本
上了分布式之后,模型服务的并不是训练完的那一份静态参数,而是持续更新的动态参数。Embedding 表被拆到多台机器后,参数更新的一致性、回放机制、版本切换都会变成复杂问题。不少团队在调研阶段把注意力全放在“怎么训得快”上,上线时才被参数不一致的问题反复折磨。所以选型时别只看训练框架,也要看配套的模型发布、版本管理和回滚机制是否支持大规模分布式更新。
5.4 我建议的调研顺序与交付物
如果现在让我重新做一次调研,我会按这个顺序推进:先量化业务指标,明确瓶颈维度;再评估压缩和优化手段,看能不能用很小的成本推迟分布式改造;如果确实需要分布式训练,对比参数服务器与混合并行的适用场景;同时把在线侧的召回-排序架构和检索方案拉通设计,不能只盯着训练。交付物上,除了技术对比文档,我强烈建议额外产出一份容量评估表和一份分阶段落地路线图,前者对应“现在的系统规模需要什么”,后者对应“未来半年到一年规模增长后要做什么”。
做完这份调研,我最深的体会是:Scaling Up 的目标不是把模型变大,而是让系统在规模变大之后仍然可控、可迭代、可上线。技术路线没有绝对的高下,只有合不合适的区别;很多人纠结选 PyTorch 还是 TensorFlow、用 Faiss 还是别的检索库,实际上真正决定成败的,是能不能在瓶颈出现之前把数据管线和在线架构一起想清楚。如果你现在正面临同样的选型压力,我建议先把你们自己的规模数字摊开,再对照这篇文章里的路线做判断——大概率会比直接追热点要靠谱得多。