反量化:反量化Q8零(q8_0)

反量化Q8零.h

cpp 复制代码
// 反量化Q8零.h ------ q8_0 量化块的反量化(8 位量化,无零偏移)
// 用途:把 q8_0 块(1 个 f16 缩放 + 32 个 int8 量化值)转为 f32 输出。
// 布局(实测确认):每块 32 元素、34 字节:d(f16, 2B) + q[32×int8, 32B]

#pragma once

// 引入基础类型(浮点/索引)
#include "公共/基础定义.h"

// 半精度转浮点:把 IEEE-754 半精度(16 位)位模式转为单精度浮点
// 说明:GGUF 文件里的缩放是 IEEE-754 半精度(1 符号位 + 5 指数位 + 10 尾数位),
//       C++ 不保证有原生的 _Float16,故用手动位操作实现(见 .cpp 内详解)
浮点 半精度转浮点(uint16_t 位);

// 反量化Q8零块:把一个 q8_0 量化块反量化为 f32
// 参数:块 = 量化数据起点(34 字节);输出 = f32 输出缓冲区(容量 ≥ 元素数);元素数 = 32
// 公式(文档注释):x_i = q_i · d,其中 q_i 是第 i 个 int8 量化值,d 是块缩放
void 反量化Q8零块(const uint8_t* 块, float* 输出, size_t 元素数);

反量化Q8零.cpp

cpp 复制代码
// 反量化Q8零.cpp ------ q8_0 量化块的反量化实现
// 用途:把 q8_0 块(1 个 f16 缩放 + 32 个 int8 量化值)转为 f32 输出。
// 布局:d(f16, 2B) + 32×int8 = 34 字节;每块 32 元素;x = q·d

#include "内核/反量化/反量化Q8零.h"

// 半精度转浮点:把 IEEE-754 半精度(16 位)位模式转为单精度浮点
// IEEE-754 半精度布局:1 符号位 | 5 指数位 | 10 尾数位
//   - 指数 = 0 且尾数 = 0:±0
//   - 指数 = 0 且尾数 ≠ 0:次正规数,值 = (-1)^符号 × 尾数 × 2^-24
//   - 指数 = 31 且尾数 = 0:±∞
//   - 指数 = 31 且尾数 ≠ 0:NaN(非数)
//   - 其余:正规数,值 = (-1)^符号 × (1 + 尾数/1024) × 2^(指数-15)
浮点 半精度转浮点(uint16_t 位) {
    // 符号位:第 15 位
    const 无符号 符号 = (位 >> 15) & 1;
    // 指数:第 14~10 位
    const 无符号 指数 = (位 >> 10) & 0x1F;
    // 尾数:第 9~0 位
    const 无符号 尾数 = 位 & 0x3FF;

    // 指数 0:零或次正规数(值 = 尾数 × 2^-24)
    if (指数 == 0) {
        // 5.9604645e-8 = 2^-24(单精度下的次正规最小步长)
        return 符号 ? -尾数 * 5.9604645e-8f : 尾数 * 5.9604645e-8f;
    }
    // 指数 31:无穷或 NaN
    if (指数 == 31) {
        if (尾数 == 0) {
            return 符号 ? -std::numeric_limits<浮点>::infinity()
                        : std::numeric_limits<浮点>::infinity();
        }
        return std::numeric_limits<浮点>::quiet_NaN();
    }
    // 正规数:(1 + 尾数/1024) × 2^(指数-15),符号另乘
    const 浮点 值 = (1.0f + 尾数 / 1024.0f) * std::pow(2.0f, static_cast<int>(指数) - 15);
    return 符号 ? -值 : 值;
}

// 反量化Q8零块:把一个 q8_0 量化块反量化为 f32
// 实现:读前 2 字节为 f16 缩放 d(小端),随后 32 字节为 int8 量化值;
//       对每个元素 x_i = q_i × d(int8 先有符号扩展到 f32 再乘)
void 反量化Q8零块(const uint8_t* 块, float* 输出, size_t 元素数) {
    // 解析 f16 缩放:小端两字节拼成 16 位模式
    const uint16_t 缩放位 = static_cast<uint16_t>(块[0] | (块[1] << 8));
    const 浮点 d = 半精度转浮点(缩放位);
    // 逐个元素反量化:q_i(int8 有符号)× d
    for (size_t i = 0; i < 元素数; ++i) {
        const int8_t q = static_cast<int8_t>(块[2 + i]);
        输出[i] = static_cast<浮点>(q) * d;
    }
}
相关推荐
doubt。2 小时前
RAG与Agent智能体项目实战教程跟练与解析(前置准备与OpenAI库基础使用)
python·ai·pip
青 春 记 忆7 小时前
LeetCode 21. 合并两个有序链表|Python 解法详解
python·算法·leetcode·链表
浩风祭月9 小时前
ChatGPT o3将在8月26日退出:Plus、Pro用户现在该迁移什么
人工智能·chatgpt·openai o3·模型迁移
布列瑟农的星空9 小时前
Milvus内部机制浅入浅出
人工智能·agent
东离与糖宝9 小时前
WorkBuddy记忆机制拆解:别再反复交代需求
人工智能
ZHOU_WUYI9 小时前
7. fastwam 模型 _predict_action_noise_with_cache部分
人工智能·pytorch·深度学习
Sagittarius_A*10 小时前
后量子密码|通识认知 03|量子威胁辟谣:Grover 算法对对称密码的影响与误区
算法·信息安全·密码学·量子计算·pqc·后量子密码
测试者家园10 小时前
AI如何发现测试人员看不到的问题?
人工智能·职场和发展·agent·智能化测试·幻觉检测·行为漂移
WoooChi10 小时前
DailyTech-20260807
人工智能·科技·业界资讯