一句话定义
暴力检索(Flat / brute-force)对查询向量与全库每一条向量逐一计算距离后取 top-k:没有近似、没有索引结构、召回率恒为 100%,是所有 ANN 索引的正确性基线与 ground truth 来源。
为什么重要
三个不可替代的角色:其一,评估——没有 Flat 算出的 ground truth,任何召回率数字都无从谈起(kp-024/025);其二,小数据最优解——十万级以内向量配合 SIMD/BLAS 批量计算,Flat 的延迟完全可接受,此时引入 ANN 是过度设计;其三,性能下界——复杂 ANN 跑不过"合理优化的暴力"时,说明索引或实现有问题。
前置知识
核心概念
- 精确扫描:O(N·d) 距离计算每次查询,无候选剪枝。
- 批量矩阵乘:把"查询×全库"组织为矩阵乘法,交给 BLAS/GPU,是暴力提速的正道。
- IndexFlatL2 / IndexFlatIP:FAISS 中两种 Flat 索引;多数向量库的"无索引/精确模式"等价于此。
- 内存账:N × d × 4 字节(float32),不建索引但向量本体必须全驻内存。
原理与机制
单条查询的代价估算:10 万条 × 768 维 = 7680 万次乘加,现代 CPU 以 AVX2/FMA + 多线程可达每秒百亿次浮点,单查询毫秒级;100 万条约几十毫秒;1000 万条秒级——这就是 Flat 的适用边界(约在十万~百万之间,取决于延迟要求与硬件)。
GPU 改变量级:FAISS 论文展示 GPU 批量暴力可在十亿级向量上达到毫秒每查询(吞吐换延迟),说明"暴力"与"规模化"并非绝对互斥——但那是吞吐场景,不是低延迟在线检索。
向量库把 Flat 作为一段(segment)的兜底扫描方式:数据刚写入、索引尚未构建的"growing segment",通常直接暴力扫描保证实时可见。
公式或模型
时间 ≈ N × d × 2 次浮点运算 / 硬件峰值FLOPS
内存 = N × d × 4 字节(float32)
例: 1e6 × 768d × 4B ≈ 2.9 GB; 1 次查询 ≈ 7.7e8 FLOPs图示
查询 q ──► [v1][v2][v3]…[vN] 逐一算距离
↓ ↓ ↓
d1 d2 dN → top-k 堆
无剪枝、无近似; 召回率恒为 1实例或案例
某内部检索服务只有 6 万条 FAQ 向量(512 维),QPS 峰值 50:选 Flat 模式,单查询约 3 毫秒,p99 < 8 毫秒,召回 100%,零索引维护成本。团队曾想"升级"HNSW,评测后发现召回无提升(本来就 100%)、只省了 1 毫秒延迟,回退 Flat——基线先行,是避免过度工程的实证。
直观类比
Flat 是"全员点名":名单 30 人逐一问话没问题,300 万人就是灾难。ANN 索引是"按花名册分班,只查可能相关班级"——省时但可能漏人。
常见误区
- "Flat 一定慢"——十万级 + SIMD/BLAS 常常快于配置不当的 ANN;先测再换。
- "有索引就删掉暴力路径"——ground truth 抽检、新写入段扫描都依赖暴力路径,成熟系统保留双路径。
- "GPU 暴力可以无限上量"——GPU 暴力赢在吞吐与批处理,单查询低延迟场景仍受 PCIe 传输与批调度约束。
自测题
- 500 万条 768 维 float32,Flat 需要多少内存?
- 为什么评估召回率必须用 Flat?
- 什么信号说明该从 Flat 换索引?
答:5e6 × 768 × 4B ≈ 14.4 GB,且必须常驻内存。
答:recall 定义为与真实 top-k 的重合度,真实 top-k 只能由精确检索产生;用另一个 ANN 当基准会把它的误差传染给你。
答:向量数增长后 p99 超业务预算、或为容纳增量被迫降批量/加机器——即触及 O(N·d) 的线性天花板。
与其他知识点的关系
kp-007/008 的参数调优以 Flat 的 ground truth 为裁判;kp-024 的指标体系以它为对照系。
延伸阅读
Johnson, Douze, Jégou, "Billion-scale similarity search with GPUs"(2017)——系统论述 GPU 暴力与批量矩阵乘在十亿级的可行性边界。