已关闭
[RFC]: A3支持IVFPQ #19
xiangjie10创建于  7月23日关闭于  27 天前
xiangjie10成员
7月23日 创建

IVFPQ 算法 A3 支持技术方案设计 (RFC)

状态 (Status): Draft
作者 (Authors): @NPU_Adaptation_Team
创建日期 (Created): 2026-07-21
更新日期 (Updated): 2026-07-22


1. 概述

1.1 简介

本提案旨在在 Ascend A3 NPU 平台上开发 IVFPQOPQ-IVFPQ 两种近似检索算法,覆盖训练、索引构建、入库、检索的完整生命周期。

主要工作包括:

  • 开发 NPU 版本的 IVFPQ 索引,支持向量维度 dim 128(IVFPQ)与 1024(OPQ-IVFPQ)两种方案
  • 支持聚类中心数 nlist 262144 与 524288 两种粒度
  • 支持 PQ 子空间数 M=32
  • 支持多卡
  • 集成 OPQ 旋转矩阵训练与应用流程
  • 支持 IP 距离度量

1.2 动机

背景

业务规模扩展至 2 亿条向量,需要将开源 Faiss 的检索能力适配至 Ascend A3 NPU 平台以获得硬件加速能力。需同时支持两种量化方案:

  • IVFPQ:128 维向量 + 32 子空间 PQ(dsub=4
  • OPQ-IVFPQ:1024 维向量 + OPQ 旋转 + 32 子空间 PQ(dsub=32

痛点

  • NPU 适配缺失:开源 Faiss 仅支持 CPU 和 GPU 检索,不支持 NPU 平台,需要在 Ascend A3 NPU 上开发 IVFPQ/OPQ-IVFPQ 算法实现

价值

  • 补齐 A3 平台在大规模库场景下的近似检索能力,覆盖 2 亿条向量业务需求
  • 在 A3 16die 配置下达到 H100 2die 持平的检索性能,验证 A3 平台在大规模检索场景下的性能表现
  • 与开源 Faiss 保持精度与 API 一致,降低迁移成本

1.3 目标

目标

  • 支持 IVFPQ (128 维)OPQ-IVFPQ (1024 维) 两套方案
  • 支持 nlist = 262144nlist = 524288 两种聚类粒度
  • 支持 IP 距离度量(METRIC_INNER_PRODUCT
  • 检索精度不低于开源 Faiss CPU 基线(使用benchmark进行测试,recall@k 不低于 CPU的,有误差需给出合理的误差来源)
  • A3 16die 检索耗时不超过 H100 2die 配置下的检索耗时
  • API 设计与 faiss 标准 API 保持一致(NpuIndexIVFPQ 对标 GpuIndexIVFPQ,OPQ 由用户在 CPU 端手动管理)

2. 用例分析

2.1 功能需求

核心功能

功能 IVFPQ (128 维) OPQ-IVFPQ (1024 维)
训练 聚类中心训练 + PQ 码本训练 OPQ 旋转矩阵训练 + 聚类中心训练 + PQ 码本训练
索引构建 倒排索引 + PQ 编码 OPQ 旋转应用 → 倒排索引 + PQ 编码
入库 向量添加到倒排列表,进行 PQ 编码 OPQ 旋转应用 → 向量添加到倒排列表,进行 PQ 编码
检索 倒排查询 + LUT 查表距离计算 + TopK OPQ 旋转应用 → 倒排查询 + LUT 查表距离计算 + TopK

参数规格

参数 取值 备注
底库规模 base 2 亿条 业务场景规模
向量维度 dim 128 / 1024 IVFPQ / OPQ-IVFPQ 两套方案
聚类中心数 nlist 262144 / 524288 两种粒度对比
PQ 子向量数 m (M) 32 固定
PQ 每子空间编码位数 nbits 8 ksub=256
子向量维度 dsub 4 / 32 128/32 / 1024/32
检索参数 nprobe 128 固定
距离度量 METRIC_INNER_PRODUCT (IP) 量化后查表距离
OPQ 旋转 仅 1024 维方案启用 128 维方案明确不启用

功能要求

  • 支持完整的训练、构建、入库、检索流程
  • 支持 IP 距离度量
  • 支持 batch 模式下的并发查询
  • 1024 维方案在训练、入库和检索时均需先执行 OPQ 旋转(由用户在 CPU 端通过 OPQMatrix::apply 手动完成),与 faiss GPU 方案一致

2.2 性能需求

精度验收标准

精度测试方法(对齐 faiss 标准 benchmark ):

  1. 使用 SIFT1M 数据集进行验证
  2. 计算 recall@1 / recall@10 / recall@100
  3. 与同参数下的开源 Faiss CPU IndexIVFPQ 基线对比

验收指标

验收项 指标
recall@k 与 CPU 基线偏差 一致(量化误差可接受范围内)

性能验收标准

性能测试方法
不同batch size下(1,2,4,8,16,32,64),测试A3 16die 与 H100 2die 的检索耗时对比

验收指标

验收项 指标
平均时延 A3 16die ≤ H100 2die

验收场景矩阵

方案 dim nlist nprobe M 度量
IVFPQ 128 262144 128 32 IP
IVFPQ 128 524288 128 32 IP
OPQ-IVFPQ 1024 262144 128 32 IP
OPQ-IVFPQ 1024 524288 128 32 IP

多卡支持:系统设计支持多卡扩展

2.3 DFX 要求

可靠性

  • 算法计算结果正确性保证(与 CPU 基线对齐)
  • 异常输入能够检查并输出异常(参数非法、显存不足等)
  • OPQ 旋转矩阵维度不匹配时抛出明确异常

可测试性

  • 开发 faiss/npu/test/TestNpuIVFPQ.cpp 单元测试
  • 开发 faiss/npu/test/scripts/test_ivfpq_accuracy.py CPU vs NPU 精度对比测试

兼容性

  • API 设计与 faiss 标准 API 保持一致(NpuIndexIVFPQ 对标 GpuIndexIVFPQ
  • OPQ-IVFPQ 由用户在 CPU 端手动管理 OPQ 旋转,与 faiss GPU 方案一致
  • 不影响 faiss 主干代码及其他算法

3. 方案设计

3.1 总体方案

设计思路

参考 faiss GPU GpuIndexIVFPQ 的分层架构,在 NPU 平台上开发 NpuIndexIVFPQ,实现 IVFPQ 算法的完整生命周期(训练、构建、入库、检索)。核心设计要点:

  1. 三阶段检索 Pipeline:L1 Coarse Quantization → L2 Subspace Distance → L3 PQ Scan + TopK。

  2. OPQ 集成:与 faiss GPU 方案一致,OPQ 旋转由用户在 CPU 端手动管理(训练 OPQMatrix + apply 旋转),NPU IVFPQ 只接收旋转后的向量,无需感知 OPQ 的存在。NPU 侧无需额外开发 OPQ 相关算子或 Cloner。

技术架构

┌──────────────────────────────────────────────────────────┐
│                   用户应用层                              │
│  用户自行管理 OPQMatrix (CPU apply 旋转)                 │
│  NpuIndexIVFPQ (接收旋转后的向量)                        │
└──────────────────────────────────────────────────────────┘
                       ↓
┌──────────────────────────────────────────────────────────┐
│                API 层 (NpuIndexIVFPQ)                    │
│  - 构造/析构、copyFrom/copyTo                            │
│  - train → indexTrainImpl_ + trainPQCodeBook_            │
│  - add   → addPaged_ → addImplCore_ (L1+L2+入库)        │
│  - search→ searchImpl_ (L1+L2+L3)                       │
│  - searchPreassigned (跳过 L1,直接 L2+L3)              │
└──────────────────────────────────────────────────────────┘
                       ↓
┌──────────────────────────────────────────────────────────┐
│                   实现层 (IVFPQ)                         │
│  ├── 训练: trainKMeansOnNpu (粗量化+PQ 码本)             │
│  ├── 入库: addPQCodes_ (PQ 编码写入倒排列表)             │
│  └── 检索: search → searchStageL1_ + L2_ + L3_          │
│      ├── L1: distance_flat_l2_mins_at_fp32               │
│      │       + topk_flat_fp32_cpu (支持分块)             │
│      ├── L2: ascendc_ivfpq_subspace_distance             │
│      └── L3: ascendc_ivfpq_search_distance_ip            │
│              + topk_ivfpq_l3_cpu                         │
└──────────────────────────────────────────────────────────┘
                       ↓
┌──────────────────────────────────────────────────────────┐
│                   算子层 (ops)                           │
│  distance_flat_l2_mins_at_fp32  (L1 距离)                │
│  topk_flat_fp32_cpu             (L1 TopK, AICPU)         │
│  ascendc_ivfpq_subspace_distance (L2 子空间距离, AICORE) │
│  ascendc_ivfpq_search_distance_ip (L3 IP 距离, AICORE)  │
│  topk_ivfpq_l3_cpu              (L3 TopK 合并, AICPU)    │
└──────────────────────────────────────────────────────────┘
                       ↓
┌──────────────────────────────────────────────────────────┐
│              ACL Runtime + A3 NPU                        │
└──────────────────────────────────────────────────────────┘

核心流程

训练阶段

训练分为粗量化训练和 PQ 码本训练两步,均通过 trainKMeansOnNpu 在 NPU 上执行 K-Means:

  • 粗量化训练:对全维向量执行 K-Means(dim=128 或 1024,nlist=262144/524288),生成聚类中心
  • PQ 码本训练:对每个子空间独立执行 K-Means(dim=dsub,nlist=ksub=256),生成 M 个子码本

OPQ-IVFPQ 方案(1024 维)在训练前需先在 CPU 训练 OPQ 旋转矩阵,再通过 OPQMatrix::apply 在 CPU 应用旋转,之后执行上述两步训练。

graph TD
    A[输入训练数据] --> B{是否启用 OPQ?}
    B -->|是| C[CPU 训练 OPQMatrix<br/>faiss::OPQMatrix::train]
    B -->|否| D[粗量化训练<br/>NPU K-Means<br/>生成 nlist 个聚类中心]
    C --> E[CPU apply 应用旋转<br/>x_rot = x · R]
    E --> D
    D --> F[PQ 码本训练<br/>NPU K-Means × M 个子空间<br/>ksub=256]
    F --> G[保存聚类中心 + PQ 码本]

    style C fill:#fff3e0
    style E fill:#e3f2fd
    style D fill:#e8f5e9
    style F fill:#e8f5e9

入库阶段

入库采用分页策略(addPaged_),大批量添加按 256 MiB 分页,每页执行三步:

  1. L1 粗量化addL1_):计算每个向量所属聚类(NPU 或 CPU)
  2. PQ 编码addL2_):按子空间量化为 M 字节编码(CPU,使用训练好的码本查表)
  3. 写入倒排列表copyVectorToDevice_):将 PQ codes + id 上传到 NPU 设备

OPQ-IVFPQ 方案在 L1 之前需先通过 OPQMatrix::apply 在 CPU 应用旋转。

graph TD
    A[输入向量] --> B{是否启用 OPQ?}
    B -->|是| C[CPU apply 旋转]
    B -->|否| D[L1: 计算所属聚类<br/>addL1_]
    C --> D
    D --> E[L2: PQ 编码<br/>addL2_ CPU 查表]
    E --> F[写入倒排列表<br/>copyVectorToDevice_]

检索阶段

检索执行 L1 → L2 → L3 三阶段 Pipeline:

  • L1:计算查询向量与 nlist 个聚类中心的距离,选 nprobe 个最近聚类。
  • L2:计算查询向量与 M×ksub 个码字的距离表(shape: batch × M × ksub)
  • L3:按倒排列表扫描 PQ codes,查表累加距离,输出 TopK

OPQ-IVFPQ 方案在 L1 之前需先通过 OPQMatrix::apply 在 CPU 应用旋转。

3.2 技术选型

不涉及

3.3 功能与性能设计

功能实现方案

OPQ 旋转矩阵集成

与 faiss GPU 方案一致,NPU 不单独实现 OPQ,也不通过 IndexPreTransform 包装。OPQ 旋转由用户在 CPU 端手动管理,NPU IVFPQ 只接收旋转后的向量,无需感知 OPQ 的存在。

流程与 GPU 一致:

  • 训练:CPU 训练 OPQMatrix → CPU apply 旋转训练数据 → 训练 NpuIndexIVFPQ(使用旋转后的数据)
  • 入库:CPU apply 旋转入库向量 → NpuIndexIVFPQ::add(旋转后的向量)
  • 检索:CPU apply 旋转查询向量 → NpuIndexIVFPQ::search(旋转后的向量)
// 1024 维 OPQ-IVFPQ 方案
faiss::OPQMatrix opq(1024, 32, 1024);
opq.train(nt, trainData);  // CPU 训练

// 对训练数据应用旋转
std::vector<float> trainDataRot(nt * 1024);
opq.apply(nt, trainData, trainDataRot.data());

// 训练 NPU IVFPQ(使用旋转后的数据)
faiss::npu::NpuIndexIVFPQConfig config;
faiss::npu::NpuIndexIVFPQ npuIvfpq(
    provider, 1024, 524288, 32, 8, faiss::METRIC_INNER_PRODUCT, config);
npuIvfpq.train(nt, trainDataRot.data());

// 入库:先旋转再添加
std::vector<float> xbRot(nb * 1024);
opq.apply(nb, xb, xbRot.data());
npuIvfpq.add(nb, xbRot.data());

// 检索:先旋转再搜索
std::vector<float> xqRot(nq * 1024);
opq.apply(nq, xq, xqRot.data());
npuIvfpq.search(nq, xqRot.data(), k, distances, labels);

影响范围

文件/模块 开发类型 说明
faiss/npu/NpuIndexIVFPQ.h 新增 NPU IVFPQ 索引公共 API
faiss/npu/impl/IVFPQ.h 新增 IVFPQ 实现层(训练、构建、入库、三阶段检索)
faiss/npu/impl/IVFPQ.cpp 新增 impl 层实现,含 L1 分块逻辑
faiss/npu/ops/ 新增 L1/L2/L3 算子实现
faiss/npu/test/TestNpuIVFPQ.cpp 新增 单元测试
faiss/npu/test/scripts/test_ivfpq_accuracy.py 新增 CPU vs NPU 精度对比测试

3.4 安全隐私与DFX设计

安全隐私

  • 不涉及用户敏感数据处理
  • 算子实现遵循安全编码规范

兼容性

  • API 设计与 faiss 标准 API 保持一致(NpuIndexIVFPQ 对标 GpuIndexIVFPQ
  • OPQ-IVFPQ 由用户在 CPU 端手动管理 OPQ 旋转,与 faiss GPU 方案一致
  • 不影响 faiss 主干代码及其他算法

可维护性

  • 代码结构清晰,分层设计(API 层 → impl 层 → 算子层)
  • L1 分块逻辑通过循环调用实现,便于后续扩展到更大 nlist
  • OPQ 集成与 GPU 方案一致,用户在 CPU 端手动管理,NPU 侧零开发

可测试性

  • 单元测试框架(Google Test)
  • 测试用例覆盖:nlist=262144/524288、dim=128/1024、OPQ-IVFPQ
  • 性能基准对齐

可靠性

  • 算法计算结果正确性保证(与 CPU 基线对齐)
  • 异常情况处理:
    • 输入向量维度与 OPQ 旋转矩阵维度不匹配时抛出异常
    • nlist 超过 524288 时抛出 FaissException
    • 显存不足时抛出明确异常而非静默截断

3.5 编程与调用设计

3.5.1 编程模型基本设计

开发环境

要求
硬件平台 Ascend A3 NPU
编程语言 C++
NPU 编程框架 ACL Runtime + AscendC 算子
构建系统 CMake (FAISS_ENABLE_NPU option)
测试框架 Google Test + Python (faiss.contrib)

开发约束

  • 必须安装 CANN 工具链与 NPU 驱动
  • 1024 维 OPQ 训练需在 CPU 端完成(依赖 faiss CPU OPQMatrix

可验收设计

验收类型 环境 标准
功能验收 A3 单卡 单元测试 + 集成测试全部通过
精度验收 A3 单卡 recall@k 与 CPU 基线一致
性能验收 A3 16die vs H100 2die 时延 A3 ≤ H100

3.5.2 接口定义与设计

3.5.2.1 NpuIndexIVFPQConfig

  • 接口描述:NPU IVFPQ 索引配置结构体,继承自 NpuIndexIVFConfig
  • 接口原型
struct NpuIndexIVFPQConfig : public NpuIndexIVFConfig {
    bool useFloat16LookupTables = false;
    bool usePrecomputedTables = false;
    bool interleavedLayout = false;
    bool useMMCodeDistance = false;
    bool useNpuTrain = false;
    ClusteringParameters cp;
    std::vector<int32_t> trainingDevices;
    bool useDistributedCoarse = false;
    int trainSamplesPerList = 40;
    int maxTrainSamples = 10000000;
};
  • 参数说明
参数名称 输入/输出 类型 描述 取值范围
useFloat16LookupTables 输入 bool 是否使用 FP16 残差距离表 true/false
usePrecomputedTables 输入 bool 是否启用预计算表模式(当前为 stub) true/false
interleavedLayout 输入 bool 是否使用交错布局(当前为 stub,仅支持 flat 布局) true/false
useMMCodeDistance 输入 bool 是否使用 GEMM 计算码本距离(调试用,当前为 stub) true/false
useNpuTrain 输入 bool 是否在 NPU 训练粗量化器和 PQ(默认 CPU 训练) true/false
cp 输入 ClusteringParameters K-Means 聚类参数 见 faiss::ClusteringParameters
trainingDevices 输入 std::vector<int32_t> NPU 训练使用的设备列表(空列表表示仅使用 config.device) 非负整数列表
useDistributedCoarse 输入 bool 是否在多个训练设备间分布式执行粗量化 K-Means true/false
trainSamplesPerList 输入 int 每个聚类中心的最大采样训练向量数 ≥1
maxTrainSamples 输入 int 单次 K-Means 训练的全局采样向量上限 ≥1

3.5.2.2 NpuIndexIVFPQ 构造与训练

  • 接口描述:构造 NPU IVFPQ 索引并训练聚类中心与 PQ 码本。
  • 接口原型
// 构造函数 1:从已训练的 CPU IndexIVFPQ 拷贝
NpuIndexIVFPQ(
    NpuResourcesProvider* provider,
    const faiss::IndexIVFPQ* index,
    NpuIndexIVFPQConfig config = NpuIndexIVFPQConfig());

// 构造函数 2:创建空索引,使用默认 Flat 量化器
NpuIndexIVFPQ(
    NpuResourcesProvider* provider,
    int dims,
    idx_t nlist,
    idx_t subQuantizers,
    idx_t bitsPerCode,
    faiss::MetricType metric = faiss::METRIC_L2,
    NpuIndexIVFPQConfig config = NpuIndexIVFPQConfig());

// 构造函数 3:创建空索引,使用用户提供的粗量化器
NpuIndexIVFPQ(
    NpuResourcesProvider* provider,
    Index* coarseQuantizer,
    int dims,
    idx_t nlist,
    idx_t subQuantizers,
    idx_t bitsPerCode,
    faiss::MetricType metric = faiss::METRIC_L2,
    NpuIndexIVFPQConfig config = NpuIndexIVFPQConfig());

void train(idx_t n, const float* x) override;
  • 参数说明
参数名称 输入/输出 类型 描述 取值范围
provider 输入 NpuResourcesProvider* NPU 资源提供者 非空
index 输入 const faiss::IndexIVFPQ* 已训练的 CPU 索引 非空(构造函数 1)
coarseQuantizer 输入 Index* 用户提供的粗量化器 非空(构造函数 3)
dims 输入 int 向量维度 正整数,需满足 dims % subQuantizers == 0
nlist 输入 idx_t 聚类中心数量 正整数
subQuantizers 输入 idx_t PQ 子空间数 ≥1,需满足 dims % subQuantizers == 0
bitsPerCode 输入 idx_t 每子空间编码位数 1~8
metric 输入 faiss::MetricType 距离度量 METRIC_L2 | METRIC_INNER_PRODUCT
n 输入 idx_t 训练向量数量 ≥ nlist × trainSamplesPerList
x 输入 const float* 训练向量数据 非空,shape [n, dims]
  • 异常处理

    • nlist 超过 524288 时抛出 FaissException
    • 训练数据量不足时抛出 FaissException
  • 调用参考代码

// 128 维 IVFPQ 方案
faiss::npu::NpuIndexIVFPQConfig config;
config.useNpuTrain = true;
auto provider = std::make_shared<faiss::npu::StandardNpuResources>();

faiss::npu::NpuIndexIVFPQ index(
    provider.get(), 128, 524288, 32, 8,
    faiss::METRIC_INNER_PRODUCT, config);

index.train(trainNum, trainData);
index.add_with_ids(ntotal, baseData, ids);
index.nprobe = 128;
index.search(nq, queryData, 100, distances, labels);
  • 其他公共方法
// CPU/NPU 数据拷贝
void copyFrom(const faiss::IndexIVFPQ* index);
void copyTo(faiss::IndexIVFPQ* index) const;

// 属性查询
int getNumSubQuantizers() const;
int getBitsPerCode() const;
int getCentroidsPerSubQuantizer() const;
size_t getCodeSize() const;

// 预分配粗量化结果的检索
void search_preassigned(
    idx_t n, const float* x, idx_t k,
    const idx_t* assign, const float* centroid_dis,
    float* distances, idx_t* labels,
    bool store_pairs,
    const SearchParametersIVF* params = nullptr,
    IndexIVFStats* stats = nullptr) const override;

3.5.2.3 OPQ-IVFPQ(1024 维)

  • 接口描述:1024 维 OPQ-IVFPQ 方案,用户在 CPU 端手动管理 OPQ 旋转,NPU IVFPQ 只接收旋转后的向量。
  • 调用参考代码
// 1024 维 OPQ-IVFPQ 方案
int dim = 1024;
int nlist = 524288;
int M = 32;

// Step 1: CPU 训练 OPQ 旋转矩阵
faiss::OPQMatrix opq(dim, M, dim);
opq.train(trainNum, trainData);

// Step 2: 对训练数据应用旋转
std::vector<float> trainDataRot(trainNum * dim);
opq.apply(trainNum, trainData, trainDataRot.data());

// Step 3: 构造并训练 NPU IVFPQ 索引(使用旋转后数据)
auto provider = std::make_shared<faiss::npu::StandardNpuResources>();
faiss::npu::NpuIndexIVFPQConfig config;
config.useNpuTrain = true;

faiss::npu::NpuIndexIVFPQ npuIvfpq(
    provider.get(), dim, nlist, M, 8,
    faiss::METRIC_INNER_PRODUCT, config);
npuIvfpq.train(trainNum, trainDataRot.data());

// Step 4: 入库(先旋转再添加)
std::vector<float> baseDataRot(ntotal * dim);
opq.apply(ntotal, baseData, baseDataRot.data());
npuIvfpq.add_with_ids(ntotal, baseDataRot.data(), ids);

// Step 5: 检索(先旋转再搜索)
npuIvfpq.nprobe = 128;
std::vector<float> queryDataRot(nq * dim);
opq.apply(nq, queryData, queryDataRot.data());
npuIvfpq.search(nq, queryDataRot.data(), 100, distances, labels);

3.5.3 编程手册设计

需要在《faiss-npu 用户指南》中新增以下章节:

  1. IVFPQ 大规模库使用指南(128 维)

    • 环境准备与依赖说明
    • nlist=262144 / 524288 配置对比
    • IP 度量使用注意事项
    • 性能调优建议
  2. OPQ-IVFPQ 使用指南(1024 维)

    • OPQ 旋转矩阵训练流程
    • CPU 端手动 apply 旋转方式
    • 1024 维场景下的内存规划
  3. 常见问题与解决方案

    • 精度不达预期:调整 nprobe、检查训练数据充分性
    • 性能不达预期:检查 batch size、NPU 利用率、AICORE/AICPU 流水
    • 显存不足:检查 nlist、M、向量数的关系

4. 缺点和风险

4.1 潜在风险

性能风险

  • A3 架构查表不亲和,可能影响检索性能

复杂度提升

  • L1 分块逻辑增加 impl 层复杂度
  • OPQ 集成由用户在 CPU 端手动管理
  • NPU 侧无需额外开发 OPQ 相关算子或 Cloner

4.2 负面影响

对 faiss 主干的影响

  • 不修改 faiss 主干代码,所有 NPU 实现在 faiss/npu/ 目录下独立开发
  • 不影响其他算法(Flat、IVFFlat 等)

4.3 实现成本

维护成本

  • 长期维护成本中等
  • 需跟进 CANN 版本更新对算子的影响
  • 需跟进 faiss 主干 OPQMatrix 实现的演进

4.4 应对措施

  • L1 性能风险:在验收前优先实测 nlist=524288 的 L1 阶段时延,若不达标则开发支持 blockSize=524288 的专用 L1 算子
  • 1024 维算子风险:在验收前优先实测 dsub=32 的子空间距离算子性能,若不达标则新增专用算子(列入未解决问题)
  • 充分的单元测试和集成测试:覆盖所有逻辑分支
  • 性能基准测试和优化:对齐 faiss benchmark 方法

5. 现有技术

faiss 开源实现

  • faiss CPU IndexIVFPQ:本提案 NPU 实现的精度基线,复用其 OPQMatrixProductQuantizerClustering 等核心组件
  • faiss GPU GpuIndexIVFPQ:架构参考,本提案 NPU 实现参照其分层设计(用户层 → 实现层 → 算子层 → 资源层)
  • faiss benchmarkbenchs/bench_all_ivf/bench_all_ivf.py 提供标准的精度/性能评估方法与公开 baseline(Indexing 1G vectors wiki

可复用的 faiss 组件

组件 来源 复用方式
OPQMatrix::train faiss CPU 直接复用,CPU 端训练 OPQ 旋转矩阵
ProductQuantizer faiss CPU 复用 PQ 码本训练逻辑
Clustering faiss CPU 复用 K-Means 聚类逻辑
OPQMatrix faiss CPU 直接复用,用户手动 apply 旋转
GpuIndexIVFPQ 架构 faiss GPU 参考分层设计模式

借鉴与差异

  • 借鉴:faiss OPQMatrix 的训练和应用方式(与 GPU 一致,用户手动管理)、faiss GPU 的分层架构设计、faiss benchmark 的 ms_per_query + recall@k 评估方法
  • 差异:本提案 OPQ 训练和应用均在 CPU(与 faiss GPU 方案一致),算子层使用 AscendC 而非 CUDA

附录

参考资料

  • faiss benchmark 代码:benchs/bench_all_ivf/bench_all_ivf.py
  • faiss Indexing 1G vectors wiki
  • faiss OPQMatrix 实现:faiss/VectorTransform.h
  • faiss GPU IVFPQ 实现:faiss/gpu/GpuIndexIVFPQ.h

术语表

术语 含义
IVFPQ Inverted File System with Product Quantization,倒排文件系统与乘积量化
OPQ Optimized Product Quantization,优化乘积量化(含旋转矩阵预处理)
nlist 倒排列表数量,聚类中心数量
M (m) 乘积量化子空间数量
nbits 每个子空间的编码位数
nprobe 检索时访问的倒排列表数量
ksub 每子空间聚类中心数,ksub = 2^nbits
dsub 子向量维度,dsub = dim / M
L1 Coarse Quantization 阶段,计算 query 与聚类中心距离并选 nprobe 个最近
L2 Subspace Distance 阶段,计算 query 与 PQ 码本的子空间距离表
L3 PQ Scan + TopK 阶段,扫描倒排列表中的 PQ codes 并输出 TopK

文档更新计划

  • RFC 评审通过后,编写《faiss-npu 用户指南》IVFPQ 大规模库与 OPQ-IVFPQ 章节
  • 编写《快速开始指南》,添加 1024 维 OPQ-IVFPQ 使用示例
likedislike
Xxiangjie10成员
7月23日 添加了label:rfc
ascend-robotascend-robot成员
7月23日 添加了label:triaged
Xxiangjie10成员
7月23日 修改了issue 的描述
yihao1234成员
7月23日 评论:

/label add triaged

likedislike
Xxiangjie10成员
7月23日 修改了issue 的描述
Xxiangjie10成员
7月24日 修改了issue 的描述
Xxiangjie10成员
7月24日 修改了issue 的描述
Xxiangjie10成员
7月24日 修改了issue 的描述
Xxiangjie10成员
7月24日 修改了issue 的描述
Xxiangjie10成员
7月24日 修改了issue 的描述
Xxiangjie10成员
7月27日 关联了里程碑:MindSDK 26.1.0
Xxiangjie10成员
7月27日 移除了里程碑
Xxiangjie10成员
7月27日 关联了里程碑:MindSDK 26.2.0
Llan_xin成员
8月14日 关联了pull request:docs: IVFPQ 算法 NPU支持技术方案设计
ascend-robotascend-robot成员
27 天前 关闭了 issue
ascend-robotascend-robot成员
27 天前 添加了label:resolved
Llan_xin成员
27 天前 关联了pull request:docs: 更新dim参数范围限制
Xxiangjie10成员
4 天前 issue状态由 TODO 改变为 DONE