Hi there 👋

Chance favors the bold.

鱿鱼游戏s2e7

January 7, 2025 · 0 min

鱿鱼游戏s2e6

January 7, 2025 · 0 min

鱿鱼游戏s2e5

January 7, 2025 · 0 min

鱿鱼游戏s2e4

January 7, 2025 · 0 min

鱿鱼游戏s2e3

January 7, 2025 · 0 min

鱿鱼游戏s2e2

January 7, 2025 · 0 min

鱿鱼游戏s2e1

January 7, 2025 · 0 min

TinyMl —— 模型量化(quantization)

Overview 模型量化(quantization)指的是用更少的bit表示模型参数,从而减少模型的大小,加速推理过程的技术。 一种常见的量化方式是线性量化(linear quantization),也叫仿射量化(affine quantization)。其实就是按比例将tensor(一般为fp32)放缩到 $2^{bitwidth}$ 的范围内,比如8bit等。我们很容易给出量化公式: $$ r = s(q - z) $$ 其中,r(real value)值得是量化前的值,q(quantized value)是量化后的值,s(scale)是放缩比例,z(zero point)相当于是一个偏移量。 如何求出$s$和$z$呢?一种简单且常见的方式是通过最大最小值来估计,即: $$ s = \frac{r_{max} - r_{min}}{q_{max} - q_{min}} $$ $r_{max}$就是这个tensor的最大值,$r_{min}$是最小值,$q_{max}$和$q_{min}$是我们指定的量化后的最大最小值。如下图所示: 有了scale, 容易得到 $z = q_{min} - \frac{r_{min}}{s}$。在实际操作中,z一般会被round到最近的整数$z = round(q_{min} - \frac{r_{min}}{s})$(有很多不同的round规则,这个有具体实现决定)。 得到量化方程: $$ q = clip(round(\frac{r}{s}) + z, q_{min}, q_{max}) $$ 代码示意如下:(实际会用pytorch已有的quantize api或者其他推理框架) def get_quantized_range(bitwidth): quantized_max = (1 << (bitwidth - 1)) - 1 quantized_min = -(1 << (bitwidth - 1)) return quantized_min, quantized_max def linear_quantize(fp_tensor, bitwidth, scale, zero_point, dtype=torch.int8) -> torch.Tensor: rounded_tensor = torch.round(fp_tensor / scale).to(dtype) shifted_tensor = rounded_tensor + zero_point quantized_min, quantized_max = get_quantized_range(bitwidth) quantized_tensor = shifted_tensor.clamp_(quantized_min, quantized_max) return quantized_tensor 上述过程被称为非对称量化(asymmetric quantization)。 ...

February 27, 2024 · 3 min

TinyMl —— 模型剪枝(pruning)

最近正在学习 MIT 6.5940, 韩松老师的课,做deep learning compression的应该都只知道。课程分为三个部分,efficient inference, domain-specific optimization, efficient training。有完整的课件,视频和实验。最后一个lab是将llama2部署在个人电脑上,非常有意思(谁不想要个自己的大模型呢)。其余lab也都可以白嫖google colab的gpu Introduction 正式介绍pruning and sparsity之前,我们先来聊聊为什么要做model compression这个事情。 Today’s Model is Too Big! 随着Large language model的出现,如GPT-3,如今的模型参数量已经达到了上百billion,别说训练,我们甚至无法在一个gpu上对其进行推理。更别提如果我们想要将其部署在其他边缘设备上。 所以当前在做inference之前,一般都会有个model-compression的过程,包括pruning(剪枝),quantization(量化),distillation(蒸馏)等。这些方法都是为了减少模型的大小,加速推理过程。这些方法也被广泛地集成到了各种加速卡,gpu中。例如nv的A100就支持structured sparsity([N:M]形式的,具体含义下文会详细介绍)。 Efficiency Metrics 我们再来看看一些 efficiency metrics,这也是我们在做inference过程中需要考虑的指标: Memory-Related Metrics # parameters model size total/peak #activations Computation-Related Metrics MACs FLOP, FLOPs # parameters 下表是一些常见结构的参数数量: Model #Parameters Linear Layer(FC) $feature_{in} * feature_{out}$ Conv Layer $c_{i} * c_{o} * k_{h} * k_{w} $ Grouped Conv Layer $c_{i} * c_{o} * k_{h} * k_{w} / g$ Depthwise Conv Layer $c_{o} * k_{h} * k_{w}$ 其中,Grouped Conv指的是将输入在channel维度进行分组,然后分别进行卷积,最后concatenate。Depthwise Conv是分组个数 $g$ 等于输入channel数的情况。 ...

February 20, 2024 · 3 min

CUDA编程模型

本系列笔记主要参考了 “Programming massively parallel processors"这本书,以及网上相关资料;不会特别详细,当作个人整理的面经 CUDA软件架构 CUDA从软件层面上提供了三层结构包括grid, block和thread。每个kernal内启动的所有线程在一个grid内。启动kernel时指定«<dimGrid, dimBlock»>,都是一个dim3结构。 gridDim的最大值范围: (x,y,z): (2^31 - 1, 65535, 65535) blockDim的最大值范围:(x,y,z): (1024, 1024, 64) 且还要同时满足:一个block内的threads数量不能超过1024(从kepler开始)。即:$ blockDim.x * blockDim.y * blockDim.z <= 1024 $ CUDA内存架构 变量声明 所在内存 作用域 生命周期 kernel内除了array的变量 register thread grid kernel内的array 变量 local thread grid __shared__ 修饰的kernel内的变量 shared block grid __device__ 修饰的全局变量 global grid application __device__ __constant__ 修饰的全局变量 constant grid application 其中 寄存器是GPU上运行速度最快的内存空间,延迟为1个时钟周期。 接下来是共享内存,共享内存是GPU上可受用户控制的一级缓存 。共享内存类似于CPU的缓存,不过与CPU的缓存不同,GPU的共享内存可以有CUDA内核直接编程控制。延迟为1~32个时钟周期。 local memory实际上就在global memory上,只是通过编译器处理成私有的、每个线程独立的一块内存区域。一般一个kernal内的数组会被处理成local memory。延迟和global memory类似。 还有texture memeory,但是和科学计算相关不大。 CUDA硬件结构 一个GPU可以看作是SM(streaming multiprocessor)的集合,每个SM包含多个SP(streaming processor,或者现在一般叫CUDA cores)。 ...

January 26, 2024 · 2 min