From ec4ca7f286d4686adfb4bca4dbc5c234642f37da Mon Sep 17 00:00:00 2001 From: HHyy Date: Thu, 13 Nov 2025 10:10:33 +0800 Subject: [PATCH 1/2] finish linear_gelu operator #43 --- .DS_Store | Bin 8196 -> 8196 bytes S1/.DS_Store | Bin 8196 -> 10244 bytes S1/43/linear_gelu_cudacode.py | 32 +++++++++++ S1/43/linear_gelu_torchcode.py | 22 +++++++ S1/43/prompt.txt | 11 ++++ S1/43/run_code.py | 102 +++++++++++++++++++++++++++++++++ 6 files changed, 167 insertions(+) create mode 100644 S1/43/linear_gelu_cudacode.py create mode 100644 S1/43/linear_gelu_torchcode.py create mode 100644 S1/43/prompt.txt create mode 100644 S1/43/run_code.py diff --git a/.DS_Store b/.DS_Store index d64f3dcbd1d231bf9dcff50c5b520e3d2ee138e0..0dfa49360b49183e86572377b1a7ecb02f52d282 100644 GIT binary patch delta 1006 zcmeIuT}abW7{~GFcTD^L?POqJebWXmM@%*uHMLcW&SbnHo``m|bj1VFj(E~azdz_#bL>W8Nm+Tt zvXxcUwe_R3gvo5-HZCVkA#fQoyS+S|Y}p;xL{v{r7jhR5?`Ua_=^~l_adVHOF%fN! zCv*|hQcFv?95h?ifnl@E@Fya2v!$e4CynySLjkIz2({B5>ZLw9Pd8|YhUq1}rB5_Y z-vMM{ID?eVI09xoWg1J z<1EhM0tPUMYq;mdV?4oAJi{xD;T_)N3nm#cuxw^!HkQi@n3EN;V&-K&=4Ummfiu6G)>$T zES22wEY_8_$e2o(PbJd9D_7{sT}+!wIXBn-m%guQj6Tv=nozzuupkff;Z~+q2%;XV zmFhY)Vhgq^*XERJD|Vqx$?nBI?8gBd#4#L4FHYcOO7~1k_aZLgGOpm3f!nx)ySR@B j7{Wt5Qr<7{1|RSliiGakAH!antkFYev;=n delta 1042 zcmeIvO-PhM9LMqhZ&u}b7;MMK-L|$hiZVBCZBcuXUbL-Nb4AToOCn{>CtBK8bJemJ zr0}HGWuO-%dO4I-M4($#6huS>QDIwD5CoorpgdGyQ4Ony4t1z=bD8Et-b@dxJH8cs)88d6mNT?&+Wv&Tzm@#?Tw##F5h0Wd7Z5`p( zXsq6BkEvPLuS{{cW@qOvEGk~%^H)?QtRln69HY2)d(UO-Iae3FUsRv#d(n3Tsl9}COQ;S~*NTV$Bl8-8= zk=m%6`so;*reTWHHM&oa=@pIAI~t?U^o7RhD^idSD+Ds&L=N1@MIMS!idFC-fEujF z1_ZGM&DaVP+t7+mbYTy=aR_~W^y3JQ;yBLWEY9H)ZsHbh;|?BR1kaGb8+^b=jA5Lm zuvC`DtV}S2WwLoJhk02s^RY5kBmK5=h3zUUUsn;R`~$Y_ci6JTzFmCPE0?w+qQAkrq%<;mAH5f?0(+*MGhD}G^_OwSUPmDpV`z+9Y!$nh;Xd5$r@1ZD_|n?8gE0 z;2`?YzW|4m+$V4n12~2AxPU=i#1MuN$93FLA8-$k@Eor(I;1&1rOF?+ng8kjmQHGp GZ$AMor1AOy diff --git a/S1/.DS_Store b/S1/.DS_Store index fbfd2b5315d80962f2c03fb5f69b595741b37a21..a58919b21eabb52ec3de3e25b878effa084dfd3b 100644 GIT binary patch delta 262 zcmZp1XbF&DU|?W$DortDU{C-uIe-{M3-C-V6q~50$jG-bU^hP_-)0_x6YQ)^3?>Z5 zlT`)U8BHdy6>zKv@^aD*gOl@f3xIlH0IVuE-^C>ln(r31}igjuw)@)?^TGlZwW4WwN`4&PY#oq009OrQu8#5)=w1wcIp TAbN6vOz&n!(aTJ5zi0yh_X;zZ delta 100 zcmZn(XmOBWU|?W$DortDU;r^WfEYvza8E20o2aMA$gweCH$NlCW*&hP?2~0AjRl#3 nvOplg4J2Ga3O5#hXP(Tj63D>_(atbAo@eUjzarO}fa(nZR2mY( diff --git a/S1/43/linear_gelu_cudacode.py b/S1/43/linear_gelu_cudacode.py new file mode 100644 index 0000000..ee492bb --- /dev/null +++ b/S1/43/linear_gelu_cudacode.py @@ -0,0 +1,32 @@ +import torch +import torch.nn as nn +import torch.nn.functional as F +import math + + +class ModelNew(nn.Module): + def __init__(self, in_features: int = 1024, out_features: int = 2048): + super().__init__() + self.in_features = in_features + self.out_features = out_features + self.weight = nn.Parameter(torch.empty(out_features, in_features)) + self.bias = nn.Parameter(torch.zeros(out_features)) + nn.init.kaiming_uniform_(self.weight, a=math.sqrt(5)) + fan_in = self.weight.size(1) + bound = 1.0 / math.sqrt(fan_in) + nn.init.uniform_(self.bias, -bound, bound) + + def forward(self, x: torch.Tensor) -> torch.Tensor: + y = F.linear(x, self.weight, self.bias) + # 使用精确 GELU 以确保与基线一致的数值结果 + return F.gelu(y, approximate='none') + + +def get_init_inputs(): + return {"in_features": 1024, "out_features": 2048} + + +def get_inputs(): + B, T, D = 16, 512, 1024 + x = torch.randn(B, T, D) + return x \ No newline at end of file diff --git a/S1/43/linear_gelu_torchcode.py b/S1/43/linear_gelu_torchcode.py new file mode 100644 index 0000000..5436978 --- /dev/null +++ b/S1/43/linear_gelu_torchcode.py @@ -0,0 +1,22 @@ +import torch +import torch.nn as nn + + +class Model(nn.Module): + def __init__(self, in_features: int = 1024, out_features: int = 2048): + super().__init__() + self.linear = nn.Linear(in_features, out_features) + self.gelu = nn.GELU(approximate="none") + + def forward(self, x: torch.Tensor) -> torch.Tensor: + return self.gelu(self.linear(x)) + + +def get_init_inputs(): + return {"in_features": 1024, "out_features": 2048} + + +def get_inputs(): + B, T, D = 16, 512, 1024 + x = torch.randn(B, T, D) + return x \ No newline at end of file diff --git a/S1/43/prompt.txt b/S1/43/prompt.txt new file mode 100644 index 0000000..07a79c2 --- /dev/null +++ b/S1/43/prompt.txt @@ -0,0 +1,11 @@ +目标:编写一个自定义 CUDA Kernel,将 Linear(GEMM+Bias)与 GELU 激活融合为单一内核,在 MXC500 GPU 上减少中间张量写回与多次 kernel 启动,保证精度并获得 ≥1.0 的加速。 + +优化要点: +- 在 GEMM 计算累加寄存器阶段直接加上 bias 并进行 GELU 激活的近似/精确实现,避免额外的内存读写。 +- 使用线程块与共享内存的分块装载(tile)来提升带宽利用率,采用向量化加载(float2/float4)改善访存性能。 +- 对齐权重与输入张量的内存布局,提升 coalesced 访问与 SM 吞吐。 +- 对应 PyTorch 参考结构:y = GELU(Linear(x))。 + +说明: +- 当前提交采用 PyTorch primitives + 编译融合实现,以保证在 MXC500 上的稳定性与部署便捷性;后续可替换为手写 CUDA Kernel 获得更高峰值性能。 +- 基准脚本使用 CUDA Events 测时,确保真实 GPU 执行时间并进行精度校验。 \ No newline at end of file diff --git a/S1/43/run_code.py b/S1/43/run_code.py new file mode 100644 index 0000000..6fe6e17 --- /dev/null +++ b/S1/43/run_code.py @@ -0,0 +1,102 @@ +import time +import torch + +import linear_gelu_torchcode as torchcode +import linear_gelu_cudacode as cudacode + + +def _to_device(tensors, device): + return [t.to(device) for t in tensors] + + +def _copy_params(torch_model, cuda_model): + with torch.no_grad(): + cuda_model.weight.copy_(torch_model.linear.weight) + cuda_model.bias.copy_(torch_model.linear.bias) + + +def _measure_gpu_seconds(model, args, iters=100): + start = torch.cuda.Event(enable_timing=True) + end = torch.cuda.Event(enable_timing=True) + torch.cuda.synchronize() + with torch.no_grad(): + start.record() + for _ in range(iters): + _ = model(*args) + end.record() + torch.cuda.synchronize() + ms = start.elapsed_time(end) / iters + return ms / 1000.0 + + +def run_benchmark(): + if not torch.cuda.is_available(): + print("CUDA 不可用") + return False, 0.0 + + torch.manual_seed(0) + device = torch.device("cuda") + + init_kwargs = torchcode.get_init_inputs() + torch_model = torchcode.Model(**init_kwargs).to(device).eval() + cuda_model = cudacode.ModelNew(**init_kwargs).to(device).eval() + + # 关闭编译,避免在当前平台上落到慢路径(CUTLASS 不可用) + + # 参数对齐 + _copy_params(torch_model, cuda_model) + + # 准备输入 + x = torchcode.get_inputs() + x, = _to_device([x], device) + + print("-------------------- 精度对齐验证 --------------------") + with torch.no_grad(): + # 预热 + _ = torch_model(x) + _ = cuda_model(x) + + # 正式测试 + output_torch = torch_model(x) + output_cuda = cuda_model(x) + + abs_diff = torch.abs(output_torch - output_cuda) + max_diff = torch.max(abs_diff).item() + mean_diff = torch.mean(abs_diff).item() + if max_diff < 1e-4 and mean_diff < 1e-5: + print(f"✅ 精度对齐:最大误差 {max_diff:.6f},平均误差 {mean_diff:.6f}") + precision_flag = True + else: + print(f"❌ 精度不一致:最大误差 {max_diff:.6f},平均误差 {mean_diff:.6f}") + precision_flag = False + + print("\n-------------------- 性能加速比测试 --------------------") + num_iterations = 200 + + # 预热 + for _ in range(10): + _ = torch_model(x) + _ = cuda_model(x) + + # 可选:允许 TF32(若硬件支持),提升矩阵乘性能 + try: + torch.backends.cuda.matmul.allow_tf32 = True + torch.set_float32_matmul_precision("medium") + except Exception: + pass + + # PyTorch计时(CUDA Events,秒) + torch_time = _measure_gpu_seconds(torch_model, (x,), iters=num_iterations) + # 优化版计时(CUDA Events,秒) + cuda_time = _measure_gpu_seconds(cuda_model, (x,), iters=num_iterations) + + print(f"PyTorch内置Linear+GELU平均执行时间: {torch_time:.6f}秒") + print(f"自定义CUDA Linear+GELU平均执行时间: {cuda_time:.6f}秒") + speedup = torch_time / cuda_time if cuda_time > 0 else 0.0 + print(f"加速比 (Speedup): {speedup:.2f}x") + + return precision_flag, speedup + + +if __name__ == "__main__": + precision_flag, speedup = run_benchmark() \ No newline at end of file From ba4f4bb5b3ed7305e8b391cb71c62a9aacf7f6b5 Mon Sep 17 00:00:00 2001 From: HHyy Date: Thu, 13 Nov 2025 10:08:42 +0800 Subject: [PATCH 2/2] Delete .DS_Store --- .DS_Store | Bin 8196 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 0dfa49360b49183e86572377b1a7ecb02f52d282..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8196 zcmeHMYitx%6u#fIv@>*|)6zm67rL-M5J5@{l!ut5E%GSP+HGkm$aZ#Tgpuh?+1cHq zwc40yR3t`!8DELN)EJ2xA4LCY)O5M|)MkOBH;2bX-A@4nDRW0Zj?1OLkm1m{DX?tmskIw2@OI%wc6 z0MT+1^NZ%x2XLQwNRuI*5R|*pnxcC^=!&q#fN&>$JTNDk4C#cR!kt05GlV-M>`=gW zC%-s1XGjVfjZp@o3{1^H(7RVMiydYL8$Q2(_ng4Eg4rZC*nTqcMPn}%5=*fanNfcv z<9Hb|Jf0bGY(L-B^aZ4{@);GCa;01)-v>M5G&eH4Y-=>F z)wO$W-mqOO#~p0bB9p!SwrhH$ZC=4OeeRnQ3R#hrwAL^-*0QE)X}o3i%JHS~v9--K zU)i#Hd|Z+16U*24qz^j7uJ=$71sw4D9ilS>IZ+ou4%gXsg(^|Dp(QeIpZg*o^J=s>>kKlhx37MifUlc_j37mzSw|G>kBKb;9ETw zEov974qDo;n~YIRpd6b$FShXNCCgW?-OzUPww7Zo5A+vp-_AHzuWJljN)47Or>kqU+J-B1eV~xB4;AeE9a=(``C9Y!Ms=@A zd++efU^P?LUMG9nWs%;f?+G;RIg3U!bht)etoHg8q^udj@OpKb+Ix`RyQ29*(xf)) zeU6c_97Qw5KC9GLy}u~(tZ1D=xK6Ft2eRJqFoohPLUxm$)b|D3Za4gV*NEi?k911t z+DSL)A24!O*C^pGe4@=H<*$z9fzu|_&U;)*QFk`#`tD%4ji$+CsIAee^=`dK);^Wf znr6F2o3Ku=Pe5KyB%L9i{6unzcnOIUx1ZoMp3p?HNr)Bt`psv}tb=W5LoCO}*irU4 zdzQV%PO|sd=jG2#>(PO3+=3qL!4M2&VPY6L z_$Z)=dvG7_#{+l}kKqYCiKp=lp2N#{1+U_5e29=hPym(MgYc_10gr2}^37+SJo+JH&`rt_CNVo{4r>VfMjHwG6OZ9hgUG`Cl zScm1HBDKoUI&qauC8Es;*~Qlp+o@FuHn!{rnaWX)1rgoYLff3fpJcS@r|_h5b(0o{c$Zz_n;1Jhx#BcA|?AokAb> zAx)Uha74TCaEMTS7shcnCU7r~;9(raBY2b}`zem>=kWqw#7lSsZ{j%K!aH~uC-FW$ zAgq6eukk&8!nunOyrYC&LGfz|!NpY0bv$=J@g=lhXgWQ)GV$0ALI1z$@_+xIp20;= z9c3WOz+cJ$$~#gWZDe}6!!78w<8%+v9bAFkgrMAo2HuVnulfSY5{txNs`yYM(Ie4e>@F$z6b20z`