GEMV朴素.h// GEMV朴素.h —— 朴素矩阵-向量乘权重量化存储激活 f32// 用途对二维权重张量做 GEMV通用矩阵-向量乘输出[行] Σ_列 权重[行][列] × 输入[列]// 说明朴素实现按块反量化到临时缓冲再乘加三维MoE 专家张量留到 Task 11#pragmaonce// 引入基础类型浮点#include公共/基础定义.h// 引入权重加载权重视图#include模型/权重加载.h// GEMV朴素二维权重矩阵 × f32 输入向量 → f32 输出向量// 参数权重 二维权重张量视图形状 [输出维度, 输入维度]维度[0] 是连续轴输入维// 输入 f32 输入向量长度 输入维度输出 f32 输出向量长度 输出维度// 说明权重按列连续存储 → 外层循环行、内层循环列符合连续访问本函数只处理二维voidGEMV朴素(const权重视图权重,constfloat*输入,float*输出);GEMV朴素.cpp// GEMV朴素.cpp —— 朴素矩阵-向量乘实现// 用途对二维权重张量做 GEMV输出[行] Σ_列 权重[行][列] × 输入[列]// 策略外层循环行、内层循环列每行按块反量化到临时缓冲再乘加朴素实现用临时缓冲#include内核/GEMV/GEMV朴素.h// 引入反量化基础按块反量化#include内核/反量化/反量化基础.h// 引入张量表块元素数/块字节数#include模型/张量表.h// 引入标准头错误处理异常#includestdexcept// GEMV朴素二维权重矩阵 × f32 输入向量 → f32 输出向量// 维度约定GGUF 维度序 dimension[0] 是内存连续轴输入维列dimension[1] 是输出维行// 存储权重按列连续 → 行 j 的数据起点 权重数据 j × 行字节数行字节数 列数/块元素数 × 块字节数voidGEMV朴素(const权重视图权重,constfloat*输入,float*输出){// 只处理二维权重三维是 MoE 专家张量Task 11 处理if(权重.信息-维度.size()!2){抛出运行错误(GEMV朴素 只支持二维权重张量实际维度数: std::to_string(权重.信息-维度.size())张量: 权重.信息-名字);}// 输入维 dimension[0]连续轴输出维 dimension[1]const索引 输入维度权重.信息-维度[0];const索引 输出维度权重.信息-维度[1];// 块尺寸每块元素数与字节数按量化类型constsize_t 每块元素块元素数(权重.信息-类型);constsize_t 每块字节块字节数(权重.信息-类型);// 每行块数 列数 / 每块元素行字节数 每行块数 × 每块字节constsize_t 每行块数输入维度/每块元素;constsize_t 行字节数每行块数*每块字节;// 临时缓冲存放一块反量化后的 f32 值向量浮点缓冲(每块元素);// 外层循环行输出维度内层循环列输入维度for(索引 行0;行输出维度;行){// 本行数据起点连续存储每行一个行块constuint8_t*行数据权重.数据行*行字节数;// 累加用双精度2048 项单精度累加会放大舍入误差与参考双精度点积对比须达 1e-5长浮点 累加0.0;for(size_t 块号0;块号每行块数;块号){// 反量化当前块到临时缓冲反量化块到浮点(权重.信息-类型,行数据块号*每块字节,缓冲.data(),每块元素);// 块内乘加输出[行] 权重[行][列] × 输入[列]for(size_t i0;i每块元素;i){累加static_cast长浮点(缓冲[i])*static_cast长浮点(输入[块号*每块元素i]);}}输出[行]static_cast浮点(累加);}}