faiss库中ivf-sq(ScalarQuantizer,标量量化)代码解读-2

文件ScalarQuantizer.h

主要介绍这里面的枚举以及一些函数内容:QuantizerType、RangeStat、ScalarQuantizer、train、compute_codes、decode、SQuantizer、FlatCodesDistanceComputer、get_distance_computer、select_InvertedListScanner

QuantizerType

量化类型中包含一些枚举类型,代码内容如下:

enum QuantizerType {QT_8bit,         ///< 8 bits per componentQT_4bit,         ///< 4 bits per componentQT_8bit_uniform, ///< same, shared range for all dimensionsQT_4bit_uniform,QT_fp16,QT_8bit_direct, ///< fast indexing of uint8sQT_6bit,        ///< 6 bits per componentQT_bf16,QT_8bit_direct_signed, ///< fast indexing of signed int8s ranging from///< [-128 to 127]};

QuantizerType 枚举内容解析

枚举值描述适用场景
QT_8bit每个分量用 8-bit 表示,分量间有独立范围(非均匀量化)。精度较高,适用于一般场景。
QT_4bit每个分量用 4-bit 表示,分量间有独立范围(非均匀量化)。精度较低但压缩率高,适用于存储敏感的大规模数据。
QT_8bit_uniform每个分量用 8-bit 表示,但所有分量共享一个范围(均匀量化)。适合数据分布较均匀的场景,计算简单,存储开销低。
QT_4bit_uniform每个分量用 4-bit 表示,所有分量共享一个范围(均匀量化)。存储极为节省,但精度较低,适合快速粗筛。
QT_fp16每个分量用 16-bit 浮点数(half-precision floating-point) 表示。高精度场景,兼顾压缩率和精度,但存储开销大于 8-bit 和 4-bit。
QT_8bit_direct直接使用无符号 uint8 值,无需量化,直接存储整数。数据本身就是无符号 8-bit 整数,例如像素值。
QT_6bit每个分量用 6-bit 表示,比 8-bit 压缩但比 4-bit 精度更高。存储与精度需求的折中选择,适合数据分布复杂但存储受限的场景。
QT_bf16使用 bfloat16(16-bit 浮点数) 表示,范围与精度介于 fp16 和 uint8 之间。适用于高动态范围但对精度要求不高的场景,例如部分深度学习推理中。
QT_8bit_direct_signed直接使用有符号 int8 值,无需量化,范围为 [-128, 127]。数据本身就是有符号的整数,例如分量可能包含负值的数据。

为什么设置为这些类型?

支持不同的精度需求

  • 数据量化需要在存储成本与精度之间找到平衡,不同类型的量化方式提供了不同的压缩率和精度。
    • 8-bit 和 4-bit:提供了常见的两种量化方式,适合大多数存储需求。
    • 6-bit:为 8-bit 和 4-bit 之间提供折中选择。
    • fp16 和 bf16:用于精度较高的场景,支持浮点值表示。
      适配多种数据分布
    • 有些数据在不同维度的范围不同(非均匀分布),需要 非均匀量化(如 QT_8bit 和 QT_4bit)。
    • 对于范围均匀的数据,可以使用 均匀量化(如 QT_8bit_uniform 和 QT_4bit_uniform),进一步减少存储复杂性。
      提高存储效率
    • QT_4bit 和 QT_4bit_uniform:只用 4-bit 表示每个分量,适合存储空间受限的大规模向量。
    • QT_6bit:比 8-bit 进一步压缩,但比 4-bit 提供更高精度。
      兼容特殊数据类型
    • QT_8bit_direct 和 QT_8bit_direct_signed:直接存储原始值,不需要量化过程,适合已经量化好的数据或离散整数值。

RangeStat

代码内容如下:

enum RangeStat {RS_minmax,    ///< [min - rs*(max-min), max + rs*(max-min)]RS_meanstd,   ///< [mean - std * rs, mean + std * rs]RS_quantiles, ///< [Q(rs), Q(1-rs)]RS_optim,     ///< alternate optimization of reconstruction error
};
枚举值描述用途与适用场景
RS_minmax根据向量的最小值和最大值生成范围:
[ min - rs * (max - min), max + rs * (max - min) ]。
- 数据分布均匀的场景
- 快速计算,但对异常值较为敏感。
RS_meanstd根据向量的均值和标准差生成范围:
[ mean - std * rs, mean + std * rs ]。
- 考虑数据集中趋势和离散程度
- 对异常值有一定鲁棒性,适合常规分布数据。
RS_quantiles根据分位数生成范围:
[ Q(rs), Q(1-rs) ]。
- 非参数方法,适合分布不均的数据
- 有效减少异常值的影响(如 5%-95% 分位数)。
RS_optim基于优化误差动态调整范围。- 重建精度要求高的场景
- 适合对误差敏感的任务,可能效率较低,但结果更精确。
  • rs 是范围缩放因子(Range Scale)。rs是用户定义的参数,根据具体场景和需求选择合格的值。
  • mean:向量分量的平均值(Mean)。
  • std:向量分量的标准差。
参数含义作用
rs范围缩放因子,控制范围的扩展程度。调节范围宽度。rs 越大,范围越宽,适合分布离散的情况;rs 越小,范围越窄,适合分布集中的情况。
mean均值,表示数据的集中趋势。用作范围的中心值,减少偏移误差。
std标准差,表示数据的离散程度。用于计算范围宽度,离散程度越大,生成的范围越宽。

ScalarQuantizer

用于将浮点转化为相对应的量化结果
头文件C语言内容:

#ifndef SCALAR_QUANTIZER_H
#define SCALAR_QUANTIZER_H#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>/* Quantizer 类型枚举 */
typedef enum {QT_8bit,            /* 8 位每分量 */QT_4bit,            /* 4 位每分量 */QT_8bit_uniform,    /* 每分量 8 位,范围统一 */QT_4bit_uniform,    /* 每分量 4 位,范围统一 */QT_fp16,            /* 16 位浮点 */QT_bf16,            /* 16 位 bfloat */QT_8bit_direct,     /* 无需额外计算的直接 8 位编码 */QT_8bit_direct_signed, /* 带符号的直接 8 位编码 */QT_6bit             /* 每分量 6 位 */
} QuantizerType;/* ScalarQuantizer 数据结构 */
typedef struct {size_t d;            /* 输入向量的维度 */size_t code_size;    /* 每个向量的编码大小(字节数) */int bits;            /* 每分量的位数 */QuantizerType qtype; /* 量化器类型 */
} ScalarQuantizer;/* 初始化函数 */
void ScalarQuantizer_init(ScalarQuantizer* sq, size_t d, QuantizerType qtype);/* 设置 derived sizes */
void ScalarQuantizer_set_derived_sizes(ScalarQuantizer* sq);/* 打印量化器信息 */
void ScalarQuantizer_print_info(const ScalarQuantizer* sq);#endif /* SCALAR_QUANTIZER_H */

实现部分:

#include "ScalarQuantizer.h"/* 初始化 ScalarQuantizer */
void ScalarQuantizer_init(ScalarQuantizer* sq, size_t d, QuantizerType qtype) {if (sq == NULL) {fprintf(stderr, "Error: ScalarQuantizer pointer is NULL.\n");exit(EXIT_FAILURE);}sq->d = d;sq->qtype = qtype;sq->code_size = 0; /* 初始化为 0 */sq->bits = 0;      /* 初始化为 0 */ScalarQuantizer_set_derived_sizes(sq);
}/* 设置 code_size 和 bits */
void ScalarQuantizer_set_derived_sizes(ScalarQuantizer* sq) {if (sq == NULL) {fprintf(stderr, "Error: ScalarQuantizer pointer is NULL.\n");exit(EXIT_FAILURE);}switch (sq->qtype) {case QT_8bit:case QT_8bit_uniform:case QT_8bit_direct:case QT_8bit_direct_signed:sq->code_size = sq->d;sq->bits = 8;break;case QT_4bit:case QT_4bit_uniform:sq->code_size = (sq->d + 1) / 2; /* 每两个分量占 1 字节 */sq->bits = 4;break;case QT_6bit:sq->code_size = (sq->d * 6 + 7) / 8; /* 位对齐处理 */sq->bits = 6;break;case QT_fp16:case QT_bf16:sq->code_size = sq->d * 2; /* 每分量 2 字节 */sq->bits = 16;break;default:fprintf(stderr, "Error: Unsupported QuantizerType.\n");exit(EXIT_FAILURE);}/* 检查初始化结果 */if (sq->code_size == 0 || sq->bits == 0) {fprintf(stderr, "Error: Invalid derived sizes.\n");exit(EXIT_FAILURE);}
}/* 打印 ScalarQuantizer 信息 */
void ScalarQuantizer_print_info(const ScalarQuantizer* sq) {if (sq == NULL) {fprintf(stderr, "Error: ScalarQuantizer pointer is NULL.\n");return;}printf("ScalarQuantizer Info:\n");printf("  Dimension (d): %zu\n", sq->d);printf("  Code Size (bytes per vector): %zu\n", sq->code_size);printf("  Bits per component: %d\n", sq->bits);printf("  Quantizer Type: %d\n", sq->qtype);
}

关键点说明

  1. ScalarQuantizer 数据结构:
  • 包含 d(维度)、code_size(编码大小)、bits(每分量位数)和 qtype(量化器类型)。
  1. 初始化函数:
  • ScalarQuantizer_init 接收维度和量化器类型作为输入,并调用 ScalarQuantizer_set_derived_sizes 设置计算派生值。
  1. 错误处理:
  • 添加了对空指针的检查以及对非法 QuantizerType 的错误处理。
  1. 位对齐逻辑:
  • 在 QT_6bit 和 QT_4bit 的计算中,处理了位对齐问题。

train、compute_codes和decode

上述函数的作用参考上一篇链接:标量量化
这里我定义的ScalarQuantizer结构体内容如下:

typedef struct ScalarQuantizer{size_t d;              /* 输入向量的维度 */size_t code_size;      /* 每个向量的编码大小(字节数) */int bits;              /* 每分量的位数 */QuantizerType qtype;   /* 量化器类型 *//* 训练参数 */float rangestat;       /* 范围统计参数 */float rangestat_arg;   /* 范围统计扩展参数 */int n_centroids;       /* 聚类中心数量 *//* 训练结果 */float* trained;        /* 存储训练的量化中心 */float* centroids;      /* 非均匀量化时的聚类中心 *//* 并行和状态跟踪 */int num_threads;       /* 并行计算的线程数量 */size_t progress;       /* 当前训练/编码的进度 *//* 高级量化支持 */int* per_dim_bits;     /* 每维分量的位数,支持动态调整 */float* residuals;      /* 残差向量存储 */int residual_levels;   /* 残差量化层数 */
} ScalarQuantizer;

然后将训练train分为3个部分:ScalarQuantizer_train(QT类4、6、8位)、train_Uniform(均匀量化训练 )和train_NonUniform(非均匀量化训练),其中train_Uniform和train_NonUniform在代码中呈现。

void ScalarQuantizer::train(size_t n, const float* x) {int bit_per_dim = qtype == QT_4bit_uniform ? 4: qtype == QT_4bit                 ? 4: qtype == QT_6bit                 ? 6: qtype == QT_8bit_uniform         ? 8: qtype == QT_8bit                 ? 8: -1;switch (qtype) {case QT_4bit_uniform:case QT_8bit_uniform:train_Uniform(rangestat,rangestat_arg,n * d,1 << bit_per_dim,x,trained);break;case QT_4bit:case QT_8bit:case QT_6bit:train_NonUniform(rangestat,rangestat_arg,n,d,1 << bit_per_dim,x,trained);break;case QT_fp16:case QT_8bit_direct:case QT_bf16:case QT_8bit_direct_signed:// no training necessarybreak;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/479133.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络 实验七 NAT配置实验

一、实验目的 通过本实验理解网络地址转换的原理和技术&#xff0c;掌握扩展NAT/NAPT设计、配置和测试。 二、实验原理 NAT配置实验的原理主要基于网络地址转换&#xff08;NAT&#xff09;技术&#xff0c;该技术用于将内部私有网络地址转换为外部公有网络地址&#xff0c;从…

Ubuntu下用Docker部署群晖系统---Virtual DSM --zerotier实现连接

Ubuntu下用Docker部署群晖系统—Virtual DSM --zerotier实现连接 1. Docker 安装 安装最新docker curl -fsSL get.docker.com -o get-docker.sh sudo sh get-docker.sh sudo docker run hello-world2.docker-compose 安装 sudo pip install docker-compose测试安装是否成功…

css—轮播图实现

一、背景 最近和朋友在一起讨论的时候&#xff0c;我们提出了这样的一个提问&#xff0c;难道轮播图的效果只能通过js来实现吗&#xff1f;经过我们的一系列的争论&#xff0c;发现了这是可以通过纯css来实现这一效果的&#xff0c;CSS轮播图也是一种常见的网页展示方式&#x…

<项目代码>YOLOv8 航拍行人识别<目标检测>

YOLOv8是一种单阶段&#xff08;one-stage&#xff09;检测算法&#xff0c;它将目标检测问题转化为一个回归问题&#xff0c;能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法&#xff08;如Faster R-CNN&#xff09;&#xff0c;YOLOv8具有更高的…

2025蓝桥杯(单片机)备赛--扩展外设之UART1的原理与应用(十二)

一、串口1的实现原理 a.查看STC15F2K60S2数据手册: 串口一在590页&#xff0c;此款单片机有两个串口。 串口1相关寄存器&#xff1a; SCON:串行控制寄存器&#xff08;可位寻址&#xff09; SCON寄存器说明&#xff1a; 需要PCON寄存器的SMOD0/PCON.6为0&#xff0c;使SM0和SM…

redmi 12c 刷机

刷机历程 一个多月前网购了redmi 12c这款手机, 价格只有550,用来搞机再适合不过了, 拆快递后就开始倒腾,网上有人说需要等7天才能解锁,我绑定了账号过了几天又忍不住倒腾,最后发现这块手机不用等7天解锁成功了,开始我为了获取root权限, 刷入了很火的magisk,但是某一天仍然发现/…

五种创建k8s的configMap的方式及configmap使用

configmap介绍 Kubernetes 提供了 ConfigMap 来管理应用配置数据&#xff0c;将配置信息从容器镜像中解耦&#xff0c;使应用更灵活、可移植。 1、基于一个目录来创建ConfigMap ​ 你可以使用 kubectl create configmap 基于同一目录中的多个文件创建 ConfigMap。 当你基于目…

【机器学习chp7】SVM

参考1&#xff0c;笔记 SVM笔记.pdf 参考2&#xff1a;王木头视频 什么是SVM&#xff0c;如何理解软间隔&#xff1f;什么是合叶损失函数、铰链损失函数&#xff1f;SVM与感知机横向对比&#xff0c;挖掘机器学习本质_哔哩哔哩_bilibili 目录 一、SVM模型 二、构建决策函…

TailwindCss 总结

目录 一、简介 二、盒子模型相关 三、将样式类写到一个类里面apply 四、一款TailWind CSS的UI库 一、简介 官方文档&#xff1a;Width - TailwindCSS中文文档 | TailwindCSS中文网 Tailwind CSS 的工作原理是扫描所有 HTML 文件、JavaScript 组件以及任何 模板中的 CSS 类…

数据结构 (6)栈的应用举例

1. 递归调用 递归函数在执行时&#xff0c;会将每一层的函数调用信息&#xff08;包括局部变量、参数和返回地址&#xff09;存储在栈中。当递归函数返回时&#xff0c;这些信息会从栈中弹出&#xff0c;以便恢复之前的执行状态。栈的后进先出&#xff08;LIFO&#xff09;特性…

Qt界面篇:QMessageBox高级用法

1、演示效果 2、用法注意 2.1 设置图标 用于显示实际图标的pixmap取决于当前的GUI样式。也可以通过设置icon pixmap属性为图标设置自定义pixmap。 QMessageBox::Icon icon(

警钟长鸣,防微杜渐,遨游防爆手机如何护航安全生产?

近年来&#xff0c;携非防爆手机进入危险作业区引发爆炸的新闻屡见报端。2019年山西某化工公司火灾&#xff0c;2018年延安某煤业瓦斯爆炸&#xff0c;均因工人未用防爆手机产生静电打火引发。涉爆行业领域企业量大面广&#xff0c;相当一部分企业作业场所人员密集&#xff0c;…

【VRChat 全身动捕】VIVE 手柄改 tracker 定位器教程,低成本光学动捕解决方案(持续更新中2024.11.26)

更新 0.0.1&#xff08;2024/11/26&#xff09;&#xff1a; 1.解决了内建蓝牙无法识别、“steamVR 蓝牙不可用” 的解决方案 2.解决了 tracker 虽然建立了连接但是在 steamVR 界面上看不到的问题 3.解决了 VIVE 基站1.0 无法被蓝牙识别 && 无法被 steamVR 搜索到 &…

大数据面试SQL题-笔记02【查询、连接、聚合函数】

大数据面试SQL题复习思路一网打尽&#xff01;(文档见评论区)_哔哩哔哩_bilibiliHive SQL 大厂必考常用窗口函数及相关面试题 大数据面试SQL题-笔记01【运算符、条件查询、语法顺序、表连接】大数据面试SQL题-笔记02【查询、连接、聚合函数】​​​​​​​ 目录 01、查询 01…

Kubeadm 安装 Kubernetes 高可用集群 v1.30.0

1、修改主机名&#xff08;各个节点&#xff09; hostnamectl set-hostname xxx2、hosts 文件加入主机名&#xff08;全部节点&#xff09; cat /etc/hosts 192.168.88.5 master1 192.168.88.6 master2 192.168.88.7 master3 192.168.88.8 node13、关闭防火墙&#xff08;全部…

网上蛋糕售卖店管理系(Java+SpringBoot+MySQL)

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装网上蛋糕售卖店管理系统软件来发挥其高效地信息处理的作用…

Ubuntu安装不同版本的opencv,并任意切换使用

参考&#xff1a; opencv笔记&#xff1a;ubuntu安装opencv以及多版本共存 | 高深远的博客 https://zhuanlan.zhihu.com/p/604658181 安装不同版本opencv及共存、切换并验证。_pkg-config opencv --modversion-CSDN博客 Ubuntu下多版本OpenCV共存和切换_ubuntu20如同时安装o…

自由学习记录(25)

只要有修改&#xff0c;子表就不用元表的参数了&#xff0c;用自己的参数&#xff08;只不过和元表里的那个同名&#xff09; 子表用__index“继承”了父表的值&#xff0c;此时子表仍然是空表 一定是创建这样一个同名的变量在原本空空的子表里&#xff0c; 传参要传具体的变…

1- 9 C 语言面向对象

面向对象的基本特性&#xff1a;封装&#xff0c;继承&#xff0c;多态 1.0 面向过程概念 当我们在编写程序时&#xff0c;通常采用以下步骤&#xff1a; 1. 将问题的解法分解成若干步骤 2. 使用函数分别实现这些步骤 3. 依次调用这些函数 这种编程风格的被称作 面向过程…

路面泥泞,坑洼,裂缝,路面损坏,马路牙检测 YOLO标记资源整理

数据集介绍 可识别常见的路面泥泞&#xff0c;坑洼&#xff0c;裂缝&#xff0c;路面损坏&#xff0c;马路牙等多种路面状况。 数据集分割 训练集89&#xff05; 2052图片 validation集8% 186图片 test集3% 78图片 预处理 自动定向&#xff1a; 已应用 自动调…