反量化:反量化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;
    }
}
相关推荐
MobotStone8 小时前
做了几个 Agent 项目后,我发现:真正拉开 AI 产品经理差距的,不是技术
人工智能·架构
孟健8 小时前
Qwen3.8-27B 本地推理实测:从 14 tok/s 到 159 tok/s 的投机解码调优
人工智能·llm·ai编程
Flynt9 小时前
HN 614 分的 16.9MB 语音模型,我在 1 核 2G 上实测了一遍
llm
思无邪669 小时前
用 AI 做 JS 逆向:从抓包到复现的完整方法论
开发语言·javascript·人工智能
百数平台9 小时前
百数AI文本知识库配置详解:本地文档上传与自定义录入、解析分段策略全说明
低代码·ai
灯澜忆梦9 小时前
【面向对象编程C++】| 基础语法
java·c++·算法
KeyAction66669 小时前
AI改写战争规则,也在改写商业规则:体系对抗时代已经到来
大数据·人工智能
小蒋观天下9 小时前
专项方案:大场景港口AI安防、多干扰环境下的算法调优与落地实操
人工智能·深度学习·算法·安全·机器学习·计算机视觉·ai大模型
冬奇Lab9 小时前
一天一个开源项目(第231篇):MiniMind —— 花3块钱、2小时,从零训练一个 64M 参数的大语言模型
人工智能·开源·资讯
揽秀亭长9 小时前
视频转脚本有哪些方法?5种方案技术拆解
人工智能·音视频