当前位置: 首页 > news >正文

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;}
}

相关文章:

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

文件ScalarQuantizer.h 主要介绍这里面的枚举以及一些函数内容&#xff1a;QuantizerType、RangeStat、ScalarQuantizer、train、compute_codes、decode、SQuantizer、FlatCodesDistanceComputer、get_distance_computer、select_InvertedListScanner QuantizerType 量化类型…...

性能测试工具Grafana、InfluxDB和Collectd的搭建

一、性能监控组成简介 1、监控能力分工:这个系统组合能够覆盖从数据采集、存储到可视化的整个监控流程。Collectd可以收集各种系统和应用的性能指标,InfluxDB提供高效的时序数据存储,而 Grafana 则将这些数据以直观的方式呈现出来。2,实时性能监控:对于需要实时了解系统状…...

【ruby on rails】dup、deep_dup、clone的区别

一、区别 dup 浅复制&#xff1a;dup 方法创建对象的浅复制。 不复制冻结状态&#xff1a;dup 不会复制对象的冻结状态。 不复制单例方法&#xff1a;dup 不会复制对象的单例方法。 deep_dup 深复制&#xff1a;deep_dup 方法创建对象的深复制&#xff0c;递归复制嵌套的对象。…...

原生微信小程序画表格

wxml部分&#xff1a; <view class"table__scroll__view"><view class"table__header"><view class"table__header__item" wx:for"{{TableHeadtitle}}" wx:key"index">{{item.title}}</view></…...

Python实现IP代理池

文章目录 Python实现IP代理池一、引言二、步骤一&#xff1a;获取代理IP1、第一步&#xff1a;爬取代理IP2、第二步&#xff1a;验证代理IP的有效性 三、步骤二&#xff1a;构建IP代理池四、使用示例1、完整的使用示例2、注意事项3、处理网络问题 五、总结 Python实现IP代理池 …...

互联网直播/点播EasyDSS视频推拉流平台视频点播有哪些技术特点?

在数字化时代&#xff0c;视频点播应用已经成为我们生活中不可或缺的一部分。监控技术与视频点播的结合正悄然改变着我们获取和享受媒体内容的方式。这一变革不仅体现在技术层面的进步&#xff0c;更深刻地影响了我们。 EasyDSS视频直播点播平台是一款高性能流媒体服务软件。E…...

32.4 prometheus存储磁盘数据结构和存储参数

本节重点介绍 : prometheus存储磁盘数据结构介绍 indexchunkshead chunksTombstoneswal prometheus对block进行定时压实 compactprometheus 查看支持的存储参数 prometheus存储示意图 内存和disk之间的纽带 wal WAL目录中包含了多个连续编号的且大小为128M的文件&#xff0c…...

C7.【C++ Cont】范围for的使用和auto关键字

目录 1.知识回顾 2.范围for 格式 使用 运行结果 运行过程 范围for的本意 作用 注意 3.底层分析范围for的执行过程 反汇编代码 分析 4.auto关键字 格式 基本用法 在范围for中使用auto 1.知识回顾 for循环的使用参见25.【C语言】循环结构之for文章 2.范围for C…...

联通云服务器部署老项目tomcat记录

1.先在服务器上安装mysql和tomcat 2.tomcat修改端口 3.在联通云运控平台配置tomcat访问端口&#xff08;相当于向外部提供可访问端口&#xff09; 4.将tomcat项目放在服务器tomcat的webapps里面 5.在mysql里创建项目数据库&#xff0c;运行sql创建表和导入数据 6.在配置文…...

剪映自动批量替换视频、图片素材教程,视频批量复刻、混剪裂变等功能介绍

一、三种批量替换模式的区别 二、混剪裂变替换素材 三、分区混剪裂变替换素材 四、按组精确替换素材 五、绿色按钮教程 &#xff08;一&#xff09;如何附加音频和srt字幕 &#xff08;二&#xff09;如何替换固定文本的内容和样式 &#xff08;三&#xff09;如何附加…...

el-dialog中调用resetFields()方法重置表单报错

前言 在开发中&#xff0c;弹框和表单是两个常见的组件&#xff0c;它们通常一起使用以实现用户交互和数据输入。然而&#xff0c;当我们尝试在弹框中调用表单的 resetFields() 方法时&#xff0c;有时会遇到报错的情况。 一、用法错误 确保 this.$refs[ruleForm].resetFields…...

分布式系统接口,如何避免重复提交

分布式系统接口&#xff0c;如何避免重复提交 1、基于Token的幂等设计原理实现步骤技术选型 2、基于Token的幂等设计原理实现步骤适用场景 3、幂等性设计原理实现方式 4、分布式锁原理实现方式适用场景 5、请求去重原理实现方式 6.前端防护原理实现方式适用场景 7.延迟队列原理…...

AI 声音:数字音频、语音识别、TTS 简介与使用示例

在现代 AI 技术的推动下&#xff0c;声音处理领域取得了巨大进展。从语音识别&#xff08;ASR&#xff09;到文本转语音&#xff08;TTS&#xff09;&#xff0c;再到个性化声音克隆&#xff0c;这些技术已经深入到我们的日常生活中&#xff1a;语音助手、自动字幕生成、语音导…...

【论文速读】| 人工智能驱动的网络威胁情报自动化

基本信息 原文标题&#xff1a;AI-Driven Cyber Threat Intelligence Automation 原文作者&#xff1a;Shrit Shah, Fatemeh Khoda Parast 作者单位&#xff1a;加拿大圭尔夫大学计算机科学学院 关键词&#xff1a;网络威胁情报&#xff0c;AI自动化&#xff0c;攻击技术和…...

什么是域名监控?

域名监控是持续跟踪全球域名系统&#xff08;DNS&#xff09;中变化以发现恶意活动迹象的过程。组织可以对其拥有的域名进行监控&#xff0c;以判断是否有威胁行为者试图入侵其网络。他们还可以对客户的域名使用这种技术以执行类似的检查。 你可以将域名监控比作跟踪与自己实物…...

vue3 发送 axios 请求时没有接受到响应数据

<script setup> import Edit from ./components/Edit.vue import axios from axios import { onMounted,ref } from vue// TODO: 列表渲染 //装数据的列表 const list ref([]) const count ref(0) const getList async () > {//通过发送 /list 请求从后端拿到列表数…...

前端使用fontfaceobserver库实现字体设置

要使用FontFaceObserver来加载设置项目本地的字体&#xff0c;先确保字体文件位于项目中或者可以从服务端获取到&#xff0c;这样就可以使用FontFaceObserver来检测并加载这些字体 主要有以下几步&#xff1a; npm或者yarn安装引入fontfaceobserver字体资源引入和font-face配置…...

【人工智能】Python常用库-PyTorch常用方法教程

PyTorch 是一个强大的开源深度学习框架&#xff0c;以其灵活性和动态计算图而广受欢迎。以下是 PyTorch 的详细教程&#xff0c;涵盖从基础到实际应用的使用方法。 1. 安装与导入 1.1 安装 PyTorch 访问 PyTorch 官方网站&#xff0c;根据系统、Python 版本和 CUDA 支持选择安…...

Android Studio安装TalkX AI编程助手

文章目录 TalkX简介编程场景 TalkX安装TalkX编程使用ai编程助手相关文章 TalkX简介 TalkX是一款将OpenAI的GPT 3.5/4模型集成到IDE的AI编程插件。它免费提供特定场景的AI编程指导&#xff0c;帮助开发人员提高工作效率约38%&#xff0c;甚至在解决编程问题的效率上提升超过2倍…...

#渗透测试#红蓝攻防#HW#漏洞挖掘#漏洞复现02-永恒之蓝漏洞

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

2024年赣州旅游投资集团社会招聘笔试真

2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...