GEMV:GEMV朴素
2026/8/9 6:44:22 网站建设 项目流程

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"// 引入标准头:错误处理异常#include<stdexcept>// 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 i=0;i<每块元素;++i){累加+=static_cast<长浮点>(缓冲[i])*static_cast<长浮点>(输入[块号*每块元素+i]);}}输出[]=static_cast<浮点>(累加);}}

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询