306 lines
10 KiB
C
306 lines
10 KiB
C
/**
|
||
* @file quantize.h
|
||
* @author @xun (xunyingya@hngwg.com)
|
||
* @brief 张量数据类型处理与量化反量化工具函数接口
|
||
* @version 2.3.0
|
||
* @date 2025-08-28 16:43
|
||
*
|
||
* Copyright (c) 2025 by CCYH, All Rights Reserved.
|
||
*
|
||
*/
|
||
#ifndef _QUANTIZE_H_
|
||
#define _QUANTIZE_H_
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
#include "nn_api.h"
|
||
|
||
#define BITS_PER_BYTE 8
|
||
|
||
/**
|
||
* @brief 根据数据类型确定该数据类型所占的字节数,并返回该字节数值
|
||
*
|
||
* @param type [IN] 数据类型
|
||
* @return unsigned int 字节数值
|
||
*/
|
||
unsigned int type_get_bytes(const int type);
|
||
|
||
|
||
/**
|
||
* @brief 根据数据类型确定该数据类型所占的字节数,并返回该字节数值
|
||
*
|
||
* @param data_format [IN] 数据类型
|
||
* @return int 字节数值
|
||
*/
|
||
int get_stride(int data_format);
|
||
|
||
|
||
/**
|
||
* @brief 根据数据类型确定该数据类型所占的bit数,并返回该bits数值
|
||
*
|
||
* @param type [IN] 数据类型
|
||
* @return unsigned int bits数值
|
||
*/
|
||
unsigned int type_get_bits(const int type);
|
||
|
||
|
||
/**
|
||
* @brief 根据维度和每个维度的大小,算出所有数据的个数
|
||
*
|
||
* @param sizes [IN] 每个维度的大小
|
||
* @param num_of_dims [IN] 维度
|
||
* @return unsigned int 所有数据的个数
|
||
*/
|
||
size_t get_element_num(size_t *sizes, unsigned int num_of_dims);
|
||
|
||
/**
|
||
* @brief 将 float32 按 IEEE-754 binary32 格式转换为 binary16(半精度)表示的位模式。
|
||
*
|
||
* 该函数将 32 位浮点数 `float` 的二进制表示压缩为 16 位浮点数(half-precision),
|
||
* 并返回其对应的 `uint16_t` 位模式表示,**不进行实际浮点运算**,只做位级转换。
|
||
*
|
||
* 常用于将神经网络模型中的参数或中间值从 float32 转为 float16 格式,以节省存储或加速推理。
|
||
*
|
||
* @param f [IN] 原始的 float32 浮点数。
|
||
*
|
||
* @return uint16_t 对应的 IEEE-754 binary16 编码的位模式。
|
||
*
|
||
* @note
|
||
* 本实现来源:njuffa,Stack Overflow (2023),用于高效 float → half 位编码转换。
|
||
* 参考链接:https://stackoverflow.com/a/16593965
|
||
*/
|
||
uint16_t fp32_to_fp16(float f);
|
||
|
||
|
||
/**
|
||
* @brief 使用非对称仿射量化(Asymmetric Affine)将 float 值量化为 uint8
|
||
*
|
||
* 该函数将输入的浮点值 `value` 通过给定的缩放系数 `q_scale` 和零点 `q_zero`,
|
||
* 映射到 [0, 255] 范围的 uint8 整数,并写入 `out_ptr` 所指向的内存
|
||
*
|
||
* @param out_ptr [OUT] 存放量化结果的 uint8 指针
|
||
* @param value [IN] 原始的 float32 值
|
||
* @param q_scale [IN] 缩放系数(scale)
|
||
* @param q_zero [IN] 零点(zero-point)
|
||
*/
|
||
void asym_affine_u8(uint8_t *out_ptr, float value, float q_scale, int q_zero);
|
||
|
||
|
||
/**
|
||
* @brief 使用动态定点(Dynamic Fixed Point)方式将 float 值量化为 int8
|
||
*
|
||
* 将输入浮点数 `value` 乘以 2^fl 进行定点缩放,并剪裁到 int8 表示范围 [-128, 127],
|
||
* 最终结果写入 `out_ptr`
|
||
*
|
||
* @param out_ptr [OUT] 存放量化结果的 int8 指针
|
||
* @param value [IN] 原始 float32 值
|
||
* @param fl [IN] 定点位置(fixed point position),即 2^fl 缩放因子
|
||
*/
|
||
void dynamic_fix_point_i8(int8_t *out_ptr, float value, int fl);
|
||
|
||
|
||
/**
|
||
* @brief 使用动态定点(Dynamic Fixed Point)方式将 float 值量化为 int16
|
||
*
|
||
* 与 int8 版本相似,该函数将输入值乘以 2^fl 并裁剪到 [-32768, 32767] 区间后,
|
||
* 写入 `out_ptr` 所指向的内存中,适用于更高精度场景
|
||
*
|
||
* @param out_ptr [OUT] 存放量化结果的 int16 指针
|
||
* @param value [IN] 原始 float32 值
|
||
* @param fl [IN] 定点位置(fixed point position),即 2^fl 缩放因子
|
||
*/
|
||
void dynamic_fix_point_i16(int16_t *out_ptr, float value, int fl);
|
||
|
||
|
||
/**
|
||
* @brief 将数据进行量化操作
|
||
*
|
||
* @param output [OUT] 量化后的结果
|
||
* @param input [IN] 待量化的数据
|
||
* @param params [IN] 量化参数
|
||
* @return int 处理后的状态码,0表示成功,其他表示失败
|
||
*/
|
||
int quantize_vector(uint8_t *output, const float *input, pnna_buffer_param_t params);
|
||
|
||
|
||
/**
|
||
* @brief 单个数据的反量化操作
|
||
* V2.0 API
|
||
*
|
||
* @param dst [OUT] 反量化后的数
|
||
* @param src [IN] 待反量化的数
|
||
* @param data_format [IN] 数据类型
|
||
* @param quant_format [IN] 量化类型
|
||
* @param fixed_point_pos [IN] 固定小数点位置
|
||
* @param scale [IN] 缩放因子
|
||
* @param zeroPoint [IN] 零点
|
||
* @return int 处理后的状态码,0表示成功,其他表示失败
|
||
*/
|
||
int dtype_to_float32_scalar(float *dst, unsigned char *src, const int data_format,
|
||
const int quant_format, const signed char fixed_point_pos,
|
||
const float scale, const int zeroPoint);
|
||
|
||
|
||
/**
|
||
* @brief 单个数据的量化操作
|
||
*
|
||
* @param dst [OUT] 量化后的数
|
||
* @param src [IN] 待量化的数
|
||
* @param data_format [IN] 数据类型
|
||
* @param quant_format [IN] 量化类型
|
||
* @param fl [IN] 固定小数点位置
|
||
* @param scale [IN] 缩放因子
|
||
* @param zerop [IN] 零点
|
||
* @return int 处理后的状态码,0表示成功,其他表示失败
|
||
*/
|
||
int float32_to_dtype_scalar(unsigned char *dst, float src, const int data_format,
|
||
const int quant_format, const signed char fl,
|
||
const float scale, const int zerop);
|
||
|
||
|
||
/**
|
||
* @brief 批量数据的仿射量化操作
|
||
*
|
||
* @param output [OUT] 量化后的数据
|
||
* @param input [IN] 待量化的数据
|
||
* @param size [IN] 待量化数据的大小
|
||
* @param stride [IN] 数据类型所占的字节数
|
||
* @param scale [IN] 缩放因子
|
||
* @param zeropoint [IN] 零点
|
||
* @param data_type [IN] 数据类型
|
||
*/
|
||
void asym_affine_vector(uint8_t *output, const float *input, const int size, const int stride,
|
||
const float scale, const int zeropoint, int data_type);
|
||
|
||
|
||
/**
|
||
* @brief 批量数据的定点浮点量化操作
|
||
*
|
||
* @param output [OUT] 量化后的数据
|
||
* @param input [IN] 待量化的数据
|
||
* @param size [IN] 待量化数据的大小
|
||
* @param stride [IN] 数据类型所占的字节数
|
||
* @param fl [IN] 固定小数点位置
|
||
* @param data_type [IN] 数据类型
|
||
*/
|
||
void dynamic_fix_point_vector(uint8_t *output, const float *input, const int size,
|
||
const int stride, const int fl, int data_type);
|
||
|
||
|
||
/**
|
||
* @brief 批量数据的仿射反量化操作
|
||
*
|
||
* @param output [OUT] 反量化后的数据
|
||
* @param input [IN] 待反量化的数据
|
||
* @param size [IN] 待反量化数据的大小
|
||
* @param scale [IN] 缩放因子
|
||
* @param zeropoint [IN] 零点
|
||
* @param data_type [IN] 数据类型
|
||
*/
|
||
void asym_affine_inverse_vector(float *output, void *input, const int size,
|
||
const float scale, const int zeropoint, int data_type);
|
||
|
||
|
||
/**
|
||
* @brief 批量数据的定点浮点反量化操作
|
||
*
|
||
* @param output [OUT] 反量化后的数据
|
||
* @param input [IN] 待反量化的数据
|
||
* @param size [IN] 待反量化数据的大小
|
||
* @param fl [IN] 固定小数点位置
|
||
* @param data_type [IN] 数据类型
|
||
*/
|
||
void dynamic_fix_point_inverse_vector(float *output, void *input,
|
||
const int size, const int fl, int data_type);
|
||
|
||
|
||
/**
|
||
* @brief 批量数据的单精度浮点数到半精度浮点数的量化操作
|
||
*
|
||
* @param output [OUT] 反量化后的数据
|
||
* @param input [IN] 待反量化的数据
|
||
* @param size [IN] 待反量化数据的大小
|
||
* @param stride [IN] 待反量化数据的步长
|
||
*/
|
||
void float_to_fp16_vector(uint8_t *output, const float *input,
|
||
const int size, const int stride);
|
||
|
||
|
||
/**
|
||
* @brief 批量数据的半精度浮点数到单精度浮点数的反量化操作
|
||
*
|
||
* @param output [OUT] 反量化后的数据
|
||
* @param input [IN] 待反量化的数据
|
||
* @param size [IN] 待反量化数据的大小
|
||
*/
|
||
void fp16_to_float_vector(float *output, short *input, const int size);
|
||
|
||
|
||
/**
|
||
* @brief 获取网络输入的量化参数
|
||
*
|
||
* @param params [OUT] 缓冲区创建的输入参数结构体指针,用于接收查询到的参数
|
||
* @param network [IN] 神经网络句柄,用于查询输入层属性
|
||
* @param index [IN] 输入层的索引,指定需要查询的输入层
|
||
* @return int 处理后的状态码,0表示成功,其他表示失败
|
||
*/
|
||
int get_input_quantize_param(pnna_buffer_param_t *params,
|
||
pnna_network network, uint32_t index);
|
||
|
||
|
||
/**
|
||
* @brief 获取网络输出的量化参数
|
||
*
|
||
* @param params [OUT] 缓冲区创建的输出参数结构体指针,用于接收查询到的参数
|
||
* @param network [IN] 神经网络句柄,用于查询输出层属性
|
||
* @param index [IN] 输出层的索引,指定需要查询的输出层
|
||
* @return int 处理后的状态码,0表示成功,其他表示失败
|
||
*/
|
||
int get_output_quantize_param(pnna_buffer_param_t *params,
|
||
pnna_network network, uint32_t index);
|
||
|
||
|
||
/**
|
||
* @brief 计算张量数据的总字节大小。
|
||
*
|
||
* 根据张量的各维尺寸和数据类型,返回对应的数据大小(以字节为单位),
|
||
* 内部通过获取元素总数并乘以每个元素的字节数来实现
|
||
*
|
||
* @param sizes [IN] 张量的维度数组(如 [1, 3, 224, 224])
|
||
* @param num_of_dims [IN] 张量的维度个数。
|
||
* @param data_type [IN] 数据类型(如 PNNA_BUFFER_FORMAT_UINT8 等),由外部类型系统定义
|
||
*
|
||
* @return uint32_t
|
||
* - 返回张量在内存中占用的总字节数
|
||
* - 若输入参数无效(如 sizes 为 NULL),则返回 0
|
||
*/
|
||
size_t get_data_size(size_t *sizes, uint32_t num_of_dims, int data_type);
|
||
|
||
|
||
/**
|
||
* @brief 将定点格式的输入张量数据进行反量化,恢复为浮点格式。
|
||
*
|
||
* 该函数根据提供的反量化参数(如 scale 和 zero_point)对输入张量数组执行反量化操作,
|
||
* 将其转换为浮点形式,用于模型输出后处理阶段
|
||
*
|
||
* 所有输出张量需由调用方预先分配,函数内部不会进行内存分配
|
||
*
|
||
* @param output_data [OUT] 反量化后的浮点 buffer_t 数组
|
||
* @param input_data [IN] 原始量化 buffer_t 数组
|
||
* @param qp [IN] 每个张量对应的反量化参数数组
|
||
* @param counts [IN] 需要处理的张量数量
|
||
*
|
||
* @return int 处理后的状态码,0表示成功,其他表示失败
|
||
*/
|
||
int nn_dequantize_vector(buffer_t *output_data, buffer_t *input_data,
|
||
pnna_buffer_param_t *qp, uint32_t counts);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif // !_QUANTIZE_H_
|
||
|