开发者
我要评分
获取效率
正确性
完整性
易理解
在线提单
论坛求助

API参考

概述

在开源hnswlib API的基础上,新增了FP16数据类型的距离计算空间类L2SpacePh和IPSpacePh,用于在ARM平台上加速FP16向量的距离计算。其余API与开源hnswlib API保持不变。FP32和FP16的距离计算实现差异体现在加载数据类型不同。FP32距离计算加载FP32类型数据,FP16距离计算加载FP16类型数据,但二者均返回FP32数据类型的计算结果。本文档将详细介绍hnswlib算法涉及的API接口。

与开源代码的差异

与开源接口差异

除此处介绍的接口差异外,其余接口与开源代码接口的使用方式保持一致。

表 1 距离计算空间接口

距离类型

数据类型

接口名称

L2

FP16

L2SpacePh

IP

FP16

IPSpacePh

除上述接口差异外,其余接口与开源代码接口的使用方式保持一致。

距离计算实现差异

FP32和FP16的距离计算实现差异体现在加载数据类型不同。FP32距离计算加载FP32类型数据,FP16距离计算加载FP16类型数据,但二者均返回FP32数据类型的计算结果。

核心空间类

FP32数据类型空间

L2Space

L2距离空间实现,适用于FP32数据类型,已针对ARM NEON进行优化。

hnswlib::L2Space space(dim); // 构造方法一
space = std::make_unique<hnswlib::L2Space>(dim); // 构造方法二

参数

  • dim: 向量维度

说明

  • 根据向量维度自动选择最优的NEON指令实现(SIMD16、SIMD4或带残差处理的版本)
  • 支持维度为任意大小,内部会自动处理对齐和残差

InnerProductSpace

内积距离空间实现,适用于FP32数据类型,已针对ARM NEON进行优化。

hnswlib::InnerProductSpace space(dim); // 构造方法一
space = std::make_unique<hnswlib::InnerProductSpace>(dim); // 构造方法二

参数

  • dim: 向量维度

说明

  • 根据向量维度自动选择最优的NEON指令实现
  • 内积距离定义为 1.0 - sum(Ai*Bi)

FP16数据类型空间(仅支持NEON实现)

L2SpacePh

L2距离空间实现,适用于FP16数据类型,使用NEON指令加速。

#ifdef USE_NEON
hnswlib::L2SpacePh space(dim); // 构造方法一
space = std::make_unique<hnswlib::L2SpacePh>(dim); // 构造方法二
#endif

参数

  • dim: 向量维度

说明

  • 仅在定义了USE_NEON宏时可用
  • 自动选择最优的NEON指令实现
  • 内存占用对比FP32显著减少

IPSpacePh

内积距离空间实现,适用于FP16数据类型,使用NEON指令加速。

#ifdef USE_NEON
hnswlib::IPSpacePh space(dim); // 构造方法一
space = std::make_unique<hnswlib::IPSpacePh>(dim); // 构造方法二
#endif

参数

  • dim: 向量维度

说明

  • 仅在定义了USE_NEON宏时可用

  • 自动选择最优的NEON指令实现

  • 内存占用对比FP32显著减少

HierarchicalNSW类

构造函数

// 创建新索引
hnswlib::HierarchicalNSW<float>* index = new hnswlib::HierarchicalNSW<float>(
    &space,                        // 空间对象
    max_elements,                  // 最大元素数量
    M = 16,                        // 每个节点的最大连接数
    ef_construction = 200,         // 构建时的ef参数
    random_seed = 100,             // 随机种子
    allow_replace_deleted = false  // 是否允许替换已删除元素
);

// 从文件加载索引
hnswlib::HierarchicalNSW<float>* index = new hnswlib::HierarchicalNSW<float>(
    &space,                        // 空间对象
    index_path,                    // 索引文件路径
    nmslib = false,                // 是否为nmslib格式
    max_elements = 0,              // 可选的新最大元素数量
    allow_replace_deleted = false  // 是否允许替换已删除元素
);

主要方法

addPoint

添加一个数据点到索引中。

void addPoint(const void* data_point, labeltype label, bool replace_deleted = false);

参数

  • data_point: 指向数据点的指针(FP32或FP16类型,取决于使用的空间类)
  • label: 数据点的标签
  • replace_deleted: 是否允许替换已删除的元素(需要构造时设置allow_replace_deleted=true

searchKnn

执行最近邻搜索,返回最近的k个结果。

std::priority_queue<std::pair<float, labeltype>> searchKnn(
    const void* query_data,                   // 查询向量
    size_t k,                                 // 搜索最近邻数量
    BaseFilterFunctor* isIdAllowed = nullptr  // 可选的过滤器
) const;

返回值

  • 优先队列,包含k个最近邻,按距离从远到近排序

searchKnnCloserFirst

执行最近邻搜索,返回最近的k个结果。

std::vector<std::pair<float, labeltype>> searchKnnCloserFirst(
    const void* query_data,                   // 查询向量
    size_t k,                                 // 搜索最近邻数量
    BaseFilterFunctor* isIdAllowed = nullptr  // 可选的过滤器
) const;

返回值

  • 向量,包含k个最近邻,按距离从近到远排序

saveIndex

将索引保存到文件。

void saveIndex(const std::string& location);

参数

  • location: 保存文件的路径

loadIndex

从文件加载索引。

void loadIndex(const std::string& location, SpaceInterface<float>* s, size_t max_elements = 0);

参数

  • location: 索引文件路径

  • s: 空间对象

  • max_elements: 可选的新最大元素数量

setEf

设置查询时的ef参数,控制查询精度和速度的权衡。

void setEf(size_t ef);

参数

  • ef: 查询时的ef参数值(应大于搜索的k值)

markDelete

标记一个元素为已删除。

void markDelete(labeltype label);

参数

  • label: 要删除的元素标签

unmarkDelete

取消标记一个已删除的元素。

void unmarkDelete(labeltype label);

参数

  • label: 要取消删除的元素标签

resizeIndex

调整索引的最大容量。

void resizeIndex(size_t new_max_elements);

参数

  • new_max_elements: 新的最大元素数量(必须大于当前元素数量)

FP32与FP16接口比较

特性 FP32接口 FP16接口
数据类型 float float16_t
内存占用 每个维度4字节 每个维度2字节
精度 高精度 中等精度
速度 更快(在支持NEON的ARM平台上)
空间类 L2Space, InnerProductSpace L2SpacePh, IPSpacePh
平台要求 无特殊要求 仅支持NEON架构