pnna2/include/quantize.h

306 lines
10 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @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
* 本实现来源njuffaStack 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_