自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(23)
  • 收藏
  • 关注

原创 AWQ量化

AWQ 全称Activation-aware Weight Quantization,激活感知权重量化量化的本质是用更少的位,来存储权重,比如说fp16 -> int4。大量节省了显存占用,同时带来一些精度损失。WQWWQWYQWXYQWXΔYQW−WXΔYQW−WX真正影响模型的不是“权重误差本身”,而是权重误差 × activation。

2026-09-20 23:55:39 157

原创 大模型的显存估算

静态部分分成权重,梯度,优化器这三个部分,根据我们之前的推算,权重占14G,然后一个权重会对应一个梯度,所以梯度部分也是14G。常说的多少多B的模型,比如qwen3.8-27B,这个B指的是参数的大小,单位是10亿,对应到计算机的所用的单位大小刚好是1G。然后时动态部分,重点是激活值,7B S=4096的模型,显存大概是30-40G,这里只是一个大概的范围。2指K和V的缓存,S是token的个数,L是层数,H是隐藏维度,最后也就是数据类型。所以一个7B的模型,用FP16加载数据的话,对应的就是。

2026-09-20 11:26:24 235

原创 mmap的使用与底层原理

mmap(Memory Map,内存映射)是。通过mmap,程序可以把文件的某一部分当作连续的内存来直接读写,而不需要再调用传统的read或write等 I/O 系统调用。

2026-09-11 16:45:25 219

原创 Cmake相关项目中Ctest 和 GoogleTest的使用与配置

想要使用GTest,一个很实用的方法是,在根目录的中添加并且之后的test目录下的内容如下重点是添加可执行程序,以及将加入链接库即可对应的测试的.cpp文件如下重点是包含头文件后,写TEST。关于的形式,左边是表明测试组,右边表明该TEST是左边测试组的哪个测试,如该例子就表明此测试是的external测试之后正常编写测试内容即可。正常构建build生成可执行程序后,就可以使用gtest了。怎么用呢,就像平时运行可执行程序一样!

2026-08-28 17:43:34 167

原创 LLM architectures

特点在于正数区域梯度不容易消失,计算简单且引入稀疏性(当输入小于 0 时,输出直接变成 0。它让神经网络能够表示弯曲的、复杂的、非线性的决策边界。本质是将norm层放在residual stream内。本质是将norm层放在residual stream外。后面发展出了GLU家族,就是将门控分支换成对应的函数。相当于一个门控的作用,根据输入x的不同产生不同的。Post-Norm:先残差相加,再归一化。Pre-Norm:先归一化,再进入子层。之后的GLU真正开始了门控的使用。之后出现的GELU和SiLU将。

2026-08-05 16:22:55 196

原创 pytorch & resource acount

一开始是Float32 后面Float16 就够了,在但是Float16的指数位较少,容易发生溢出,BFloat16将一部分尾数位变成指数位,解决了该问题,虽然失去了一点精度,但是动态范围更大。一般 情况下matmul是compute-bound而其他的element-wise是memory-bound。NVIDIA 标注的性能规格是基于稀疏矩阵的,稠密矩阵的FLOP/s=稀疏矩阵FLOP/s / 2。实际的FLOP/s除以期望的FLOP/s 通常在0.5已经比较优了。BF16用于参数、激活值、梯度。

2026-08-04 16:33:00 180

原创 cuTile助力高性能Kernel高效开发

这两个函数对数据进行SM(不一定是shared_memory)和Global Memory之间的搬运,但是正如前文所说,CUDA是显式控制shared_memory的,cuTile则对此进行了封装。一言以蔽之,对于GPU的workload,最便捷的方法是直接调用library提供的grid级的操作,但是要有特殊追求是就会陷入SIMT级别的较为繁琐的编程,Tile介于二者之间。不是指单纯的下标0,下标1,而是以tile_size为间隔开始的下标,非常方便。SIMT风格的编程的代码复杂度较高。

2026-07-31 23:45:20 231

原创 Attention和FlashAttention的Cuda实现

另有把KV放在外层的flash attention版本,相比该版本,Q放在外层使得SM处理的颗粒度更细,并发度更高。这里的B矩阵也是按行处理,相当于做了一个隐式的转置。代码的思路还是比较清晰的,这里不做过多讲解。计算步骤如下,我们稍作解读。

2026-07-25 20:29:56 165

原创 RMSNorm算子及其优化

这与我们之前所处理的softmax算子类似,都是一个block处理一组数据,只不过这里是每个线程处理个数据,当size>1024时,才开始一个线程处理多个数据。这里没有什么好说的。重点关注的地方是size不是pack_size的倍数时需要处理后续留下来的尾巴,其他的没有重点要讲的。RMSNorm的计算流程是给定输入向量。,RMSNorm的输出为。

2026-07-24 18:27:10 170

原创 CUDA 中的Transpose与数据排布优化

同一个warp内,同一条指令,不同线程都要访问bank0,且访问的是bank0中的不同数据(这里是线程0要访问存储在bank0中的data[0],而线程16要访问存储在bank0中的data[32]),就会发生bank conflict。这里除了ix,和iy是每个线程处理的坐标以外,bidx和之后irow,icol的作用是既然要转置,所以to部分的ix,iy也是对应转置后的版本。因为在一个warp中,threadId.x是连续的,共享内存除了本身的速度快,这里还起了一次中转的作用。所以一个warp执行。

2026-07-24 14:04:16 167

原创 CUDA的原子操作

在并行计算中,多个线程同时更新同一数据可能导致数据竞争,引发结果不一致问题。为解决这一挑战,CUDA 提供了原子函数,借助硬件支持确保操作的原子性,保障共享数据在并发访问时的正确性与高效性。本节重点解析原子函数的实现机制,以原子加(atomicAdd)为例,深入探讨其在硬件层面的执行原理及其对性能的影响。随后,我们通过一个完整的并行直方图计算示例,演示如何利用原子加操作高效构建直方图,并结合具体代码分析性能优化策略与潜在瓶颈,帮助开发者更好地应用原子操作进行高效 GPU 编程。

2026-07-20 10:17:10 232

原创 matmul算子实现及优化

矩阵乘法很重要。

2026-07-20 09:31:39 186

原创 cuda reudce算子实现及优化

如何高效、正确地将一个庞大的数据集“坍缩”为一个单一的数值。问题:传统的汇总操作(如求和)是串行的。如果按照这个逻辑,无论 GPU 有多少核心,都只能有一个核心在工作。归约的解法:利用数学上的结合律,将线性执行转化为树状执行。NNN个线程同时将数据两两配对相加,得到N2N/2N/2个结果。N2N/2N/2个线程继续配对相加,直到最后剩下一个值。这样将时间复杂度从ONO(N)ON降到了Olog⁡NO(\log N)Olo。

2026-07-16 19:12:13 211

原创 softmax算子实现及其在GPU下的优化

相比GPU实现一,实现二同样是一个线程块处理以组数据,不同的是线程块中一个线程处理多个数据,同时又多个线程并行,并发度更高。每次规约时,每个参与运算的线程都是读取特定步长的跨度的数据,因此可以用洗牌指令完成读取,而不是用共享内存。有一点需要提一下,N越大(数据越多),block_size越大(warp数量越多),GPU运算的优势越大。每行分配一个线程,blockdim.x=1,该线程唯一负责完成该行所有元素的softmax计算。给出一个NxC的张量(N行C列,线性存储),softmax,cpu实现如下。

2026-07-16 14:38:35 235

原创 CUDA的显存模型与显存分层模型

GPU的核心结构:它是是围绕一个流式多处理器(SM)的扩展阵列搭建的:负责内存加载和存储操作,用于在寄存器和全局内存、共享内存之间传输数据。:专门执行特殊数学运算,比如三角函数、指数函数和倒数等,提升计算复杂函数的效率。:是NVIDIA GPU中的基本计算单元,负责执行基本的算术逻辑运算(如加法、乘法),是实现并行计算的核心组件。:负责将指令从线程束调度器发送到适当的执行单元(例如 CUDA Cores、LD/ST 或 SFU)。

2026-07-08 22:05:50 150

原创 用给定数字构造小于S的最大数,二叉树的最大宽度

贪心 + 回退高位能相等就相等;一旦某位能变小,后面全部补最大值;当前位放不了,就往前回退;完全相等也要回退;回退不了就少一位。

2026-05-28 13:39:37 201

原创 好看的串&&数据传输网络最小时延

小华有一个好看的串A。对于一个串,每次可以选择其中任意两个相邻且相同的字符,然后删除其中一个。aabbbbaa如果串X可以通过若干次删除操作得到串A,则X也是好看的串。现在给定目标串A和字符串S,需要计算S中有多少个子串是好看的串。位置不同的相同子串算不同子串。

2026-05-22 22:01:55 177

原创 树的合并以及带限制条件的单源最短路

层序建树 + 找同名根节点 + 递归判冲突 + 递归合并 + 层序输出不能用数组下标法建树不是从两个根直接合并。

2026-05-19 15:28:29 395

原创 用C语言实现C++中 栈stack

stack需要包含的头文件:栈stack满足先进后出的特点。

2025-01-11 23:58:31 840 9

原创 单链表常见OJ(上)

五道常见链表OJ

2025-01-11 12:34:18 692 6

原创 从零到快排求解第K大数

背景打算认真踏实的敲一遍以前做过的题目,发现自己忘了,于是就搜“第K大数”,我发现csdn上的讲解有的就是一坨,遂自己写一篇从零开始的题解;

2024-12-29 15:20:18 741 3

原创 时间复杂度

2选定最高阶:时间复杂度由操作数中的最高阶的向来决定,这是因为在n趋于无穷大时,最高阶的项将发挥主导作用,其他项的影响都可以忽略。其中O(1)代表常数阶,即无论n多大,操作次数固定,O(logn)一般指的是以2为底的对数,如排序后的二分查找。2n^2+6n+8 复杂度为O(n^2)比如这段while代码,包含两个for循环,那么时间复杂度就是n+n=2n忽略系数之后的n。O(n^2):嵌套循环(内外层的时间复杂度都为O(n))O(n):遍历数组,遍历链表。

2024-12-10 17:42:44 246 1

原创 初见指针~

为了方便内存的使用与管理,内存被划分为一个个内存单元,每个内存单元的大小是一个字节(8bit,1Byte),并对每一个内存单元进行编号。指针变量是用来存放地址的,一个地址的存放需要多大空间,那么对应的指针变量的大小就有多大(用sizeof)。C语言中创建变量的本质其实是在内存中申请空间,编译器在处理数据的时候,并不看变量的名字,而是通过地址找内存单元(&——取地址操作符)。计算机中各硬件需要协同工作,计算机中的编址(给内存编号)并不是把每个字节的地址记录下来,而是通过硬件设计完成的,是已经规定好的。

2024-10-14 18:18:39 278 1

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除