Faiss 16 位标量量化
从 2.13 版本开始,OpenSearch 支持在 OpenSearch 内对 Faiss 引擎执行标量量化。在 Faiss 引擎中,标量量化器 (SQfp16) 执行 32 位和 16 位向量之间的转换。在摄入时,当您将 32 位浮点向量上传到 OpenSearch 时,SQfp16 会将它们量化为 16 位浮点向量,并将量化后的向量存储在向量索引中。
在搜索时,SQfp16 将向量值解码回 32 位浮点值以进行距离计算。SQfp16 量化可以将内存占用减少 2 倍。此外,当向量值之间的差异相对于消除其两个最低有效位引入的误差较大时,它只会导致召回率的最小损失。当与 SIMD 优化结合使用时,SQfp16 量化还可以显著降低搜索延迟并提高索引吞吐量。
Windows 不支持 SIMD 优化。在 Windows 上使用 Faiss 标量量化可能会导致性能显著下降,包括索引吞吐量降低和搜索延迟增加。
使用 Faiss 标量量化
要使用 Faiss 标量量化,请在创建向量索引时将 k-NN 向量字段的 method.parameters.encoder.name
设置为 fp16
PUT /test-index
{
"settings": {
"index": {
"knn": true,
"knn.algo_param.ef_search": 100
}
},
"mappings": {
"properties": {
"my_vector1": {
"type": "knn_vector",
"dimension": 3,
"space_type": "l2",
"method": {
"name": "hnsw",
"engine": "faiss",
"parameters": {
"encoder": {
"name": "fp16"
},
"ef_construction": 256,
"m": 8
}
}
}
}
}
}
您可以选择在 method.parameters.encoder
中指定参数。有关 encoder
对象参数的更多信息,请参阅SQ 参数。
fp16
编码器将 32 位向量转换为其对应的 16 位向量。对于此编码器类型,向量值必须在 [-65504.0, 65504.0] 范围内。为定义如何处理超出范围的值,前面的请求指定了 clip
参数。默认情况下,此参数为 false
,任何包含超出范围值的向量都将被拒绝。
当 clip
设置为 true
(如前面的请求所示)时,超出范围的向量值将被向上或向下舍入,使其位于支持的范围内。例如,如果原始的 32 位向量是 [65510.82, -65504.1]
,则该向量将作为 16 位向量 [65504.0, -65504.0]
进行索引。
仅当很少的元素超出支持范围时,我们才建议将 clip
设置为 true
。舍入值可能会导致召回率下降。
以下示例方法定义指定了 Faiss SQfp16 编码器,该编码器会拒绝任何包含超出范围向量值的索引请求(因为 clip
参数默认为 false
)
PUT /test-index
{
"settings": {
"index": {
"knn": true,
"knn.algo_param.ef_search": 100
}
},
"mappings": {
"properties": {
"my_vector1": {
"type": "knn_vector",
"dimension": 3,
"space_type": "l2",
"method": {
"name": "hnsw",
"engine": "faiss",
"parameters": {
"encoder": {
"name": "sq",
"parameters": {
"type": "fp16"
}
},
"ef_construction": 256,
"m": 8
}
}
}
}
}
}
在摄入过程中,请确保每个向量维度都在支持的范围 ([-65504.0, 65504.0]) 内。
PUT test-index/_doc/1
{
"my_vector1": [-65504.0, 65503.845, 55.82]
}
在查询时,查询向量没有范围限制
GET test-index/_search
{
"size": 2,
"query": {
"knn": {
"my_vector1": {
"vector": [265436.876, -120906.256, 99.84],
"k": 2
}
}
}
}
内存估算
在最佳情况下,Faiss SQfp16 量化器生成的 16 位向量所需的内存是 32 位向量所需内存的 50%。
HNSW 内存估算
分层可导航小世界 (HNSW) 所需的内存估计为 1.1 * (2 * dimension + 8 * m)
字节/向量,其中 m
是在图构建过程中为每个元素创建的最大双向链接数。
例如,假设您有 100 万个向量,维度为 256,m
为 16。内存需求可估算如下:
1.1 * (2 * 256 + 8 * 16) * 1,000,000 ~= 0.656 GB
IVF 内存估算
IVF 所需的内存估计为 1.1 * (((2 * dimension) * num_vectors) + (4 * nlist * dimension))
字节/向量,其中 nlist
是用于将向量分区到的桶的数量。
例如,假设您有 100 万个向量,维度为 256,nlist
为 128。内存需求可估算如下:
1.1 * (((2 * 256) * 1,000,000) + (4 * 128 * 256)) ~= 0.525 GB