L2Norm朴素.h
// L2Norm朴素.h —— L2 范数归一化(沿向量整体)朴素标量实现声明// 用途:DeltaNet 中 q/k 按每个 (头, token, seq) 切片独立归一——本函数处理单个切片,外层负责切片遍历#pragmaonce// 引入基础类型(浮点/size_t 别名)#include"公共/基础定义.h"// L2Norm朴素:对单向量按 L2 范数(欧氏长度)归一// 公式:$$ \hat{x}_i = \frac{x_i}{\sqrt{\sum_{j} x_j^2 + \epsilon}} $$// 纯文本:x̂_i = x_i / sqrt( Σx_j² + ε )// 注意与 RMSNorm 区别:RMSNorm 除数带 1/d(除以均值),L2Norm 除数不带 1/d(除以总和)。// 参数:输入 = 待归一化向量起点;输出 = 结果起点;元素数 = 切片长度;// epsilon = 防除零常数(DeltaNet 用 1e-6)// 说明:调用方负责把 q/k 按 (头, token, seq) 切分后对每个切片调用本函数voidL2Norm朴素(constfloat*输入,float*输出,size_t 元素数,floatepsilon);
L2Norm朴素.cpp
// L2Norm朴素.cpp —— L2 范数归一化(沿向量整体)朴素标量实现// 用途:把单切片向量缩放到单位长度(欧氏范数 = 1),除数不带 1/d(区别于 RMSNorm)#include"内核/归一化/L2Norm朴素.h"// 引入标准头:平方根 sqrt#include<cmath>// L2Norm朴素:按 L2 范数归一单向量// 公式:x̂_i = x_i / sqrt( Σx_j² + ε )// 实现:先累加全部元素的平方和(double 累加防精度损失),开方后逐元素相除voidL2Norm朴素(constfloat*输入,float*输出,size_t 元素数,floatepsilon){// 第一步:累加平方和(不除以元素数——这是与 RMSNorm 的关键区别)double平方和=0.0;for(size_t i=0;i<元素数;++i){平方和+=static_cast<double>(输入[i])*输入[i];}// 第二步:L2 范数 = sqrt( Σx_j² + ε )constdouble范数=std::sqrt(平方和+static_cast<double>(epsilon));// 第三步:逐元素除以范数(double 中间量保证精度)for(size_t i=0;i<元素数;++i){输出[i]=static_cast<浮点>(static_cast<double>(输入[i])/范数);}}