半精度浮点(FP16 / BF16)
fp16 与 bf16 把每个坐标用 16 位而非 32 位存储,把码内存减半且近似
无损。它们没有量化器专属的 JSON 参数;二者的唯一差异是浮点格式自身的
位布局。
实现:
src/quantization/scalar_quantization/half_precision_quantizer.cpp, 类型特征在half_precision_traits.h。 可运行示例:examples/cpp/321_index_fp16_hgraph.cpp。
FP16 与 BF16 一览
| 格式 | 符号位 | 指数位 | 尾数位 | 有效范围 | 精度 |
|---|---|---|---|---|---|
fp16 | 1 | 5 | 10 | ~±6.55e4 | 约 3 位十进制 |
bf16 | 1 | 8 | 7 | 与 fp32 相同(~±3.4e38) | 约 2 位十进制 |
实践含义:
fp16保留更多尾数位——对取值大致在[-1, 1]的归一化嵌入精度更 好。是 cosine 归一化向量的标准选择。bf16保留与fp32一致的指数范围——对原始、未归一化的特征(如 加权和、累加器式嵌入)更安全。相对fp16,在接近零的取值上损失一些 精度。
不确定时:归一化嵌入选 fp16,未归一化或范围较宽的数据选 bf16。
何时使用
- 在
fp32基线之上作为“即插即用“的内存优化。在标准基准(SIFT、GIST、 Glove、句向量)上召回损失通常低于 1%。 - 作为精确重排存储,体积仅为 fp32 的一半:
precise_quantization_type: "fp16"或"bf16"配合use_reorder: true。 - 高维浮点向量,32 位存储成为瓶颈时。
内存代价
仅码本身每向量 2 × dim 字节。
参数
fp16 与 bf16 均没有量化器专属 JSON 参数。
{
"dtype": "float32",
"metric_type": "l2",
"dim": 768,
"index_param": {
"base_quantization_type": "fp16",
"max_degree": 32,
"ef_construction": 300
}
}
将 "fp16" 替换为 "bf16" 即可切换格式。输入 dtype 仍是 "float32":
量化器会在运行时转换。
训练
不需要。fp16 与 bf16 均不设置 NEED_TRAIN。
度量兼容性
l2、ip、cosine——全部支持。cosine 通过先归一化输入再以 16 位精度
存储实现。
何时不要使用
- 当你还需要一个内存更激进的基础量化器(如
sq8或pq)——它们已经 把存储压到远低于 2 字节/维。 - 当你需要精确距离(用
fp32)。