Faiss 16位标量量化

UDB-SX 支持在 Faiss 引擎内部执行标量量化。在 Faiss 引擎中,标量量化器执行 32 位向量与 16 位向量之间的转换。在数据摄入时,当您将 32 位浮点向量上传到 UDB-SX 时,SQfp16 会将它们量化为 16 位浮点向量,并将量化后的向量存储在向量索引中。

在搜索时,SQfp16 将向量值解码回 32 位浮点值以进行距离计算。SQfp16 量化可以将内存占用减少一半。此外,当向量值之间的差异远大于因消除其最低有效两位而引入的误差时,量化导致的召回率损失微乎其微。当与 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": "sq"
            },
            "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 内存估算

分层可导航小世界图所需的内存估算为 1.1 * (2 * 维度 + 8 * m) 字节/向量,其中 m 是在图构建过程中为每个元素创建的最大双向链接数。

举例说明,假设您有 100 万个向量,维度为 256,m 值为 16。内存需求估算如下:

1.1 * (2 * 256 + 8 * 16) * 1,000,000  0.656 GB

IVF 内存估算

IVF 所需的内存估算为 1.1 * (((2 * 维度) * 向量数) + (4 * nlist * 维度)) 字节/向量,其中 nlist 是将向量分区到的桶的数量。

举例说明,假设您有 100 万个向量,维度为 256,nlist 值为 128。内存需求估算如下:

1.1 * (((2 * 256) * 1,000,000) + (4 * 128 * 256))   0.525 GB