关于 DeepSeek-R1-Distill-Qwen-1.5B 显存占用比下载权重高非常多的现象分析
现象从 huggingface 上下载下来的 DeepSeek-R1-Distill-Qwen-1.5B 模型权重大小只有 3.5GB,但是加载到 GPU 上之后,占用显存达到 5.4GB,多了 1.9GB。 排查显存占用比权重多 1.9GB 的原因应该是模型在创建的时候申请了权重以外的内存,这部分内存没有体现在权重的大小中。 使用 pytorch 查看显存占用pytorch 博客 Understanding GPU Memory 1: Visualizing All Allocations over Time 中给出了 pytorch 内部的显存统计方法,函数都定义在 torch.cuda.memory 中。具体代码可以参考官方博客,下面展示显存统计结果。 可以看到从程序开始到结束,显存一直都是 5.4GB 左右,最上方有一小部分激活占用的显存,但是由于我们输入非常短,所以占用很小。从这个结果我们可以想象到,模型总显存占用比权重多的那部分显存在模型一开始就创建了,后续的应用层是无法操作的。 使用 transformers 查看显存占用transformers 的 AutoMo...
float16-series-1-glance
1. 浮点数表示 类型 符号位 指数位 尾数位 总位数 FP32 1 8 23 32 FP16 1 5 10 16 BF16 1 8 7 16
opencl-tips
为什么从 CPU 上拷贝到 Image 里使用的是【CPU -> Buffer -> Image】而不是【CPU -> Image】?因为 Image 一般都是用 RGBA 格式,需要填充为 4 通道,以及长宽 4 对齐等需求。如果在 CPU 上做,需要对内存进行补边再拷贝到 Image 里;不如【CPU -> Buffer -> Image】 的兼容性更好。前者不用考虑 clEnqueueWriteBuffer 的参数,在 buffer_to_image 内核中注意边界条件即可。 为什么大部分 OpenCL 编程使用的都是全局内存,少用局部内存/共享内存?【不使用局部内存】可能是一种编程规范。这样做有以下优点: 可以通过在线调优 local_work_size 的方式找到最优值,从而提高性能,因为使用局部内存可能需要已知的 lws 大小;如果不需要局部内存,lws 的值可以是任意的,从而可以更灵活地调优。 不同厂商(vendor)的实现可能不同,使用全局内存可以避免不同厂商的差异。比如 mali GPU 使用的是 global memo...
将 ViT 的第一个卷积层转为 MatMul,要求步长和卷积核相等
ViT 卷积层为了将输入的图片转为 patch,然后送入到 Transformer 中,ViT 第一个卷积的步长和卷积核大小是相等的,都是 16。如下图所示, 某些框架可能不支持这么大的 Conv 步长,导致无法转换相应模型。 MatMul卷积可以使用 im2col 加 matmul 来实现,但是由于 im2col 可能效率不高,所以一般不使用这个方式。 不过我们注意到 ViT 第一个卷积层里的步长和卷积核大小是相等的,所以我们可以用 reshape + transpose 来实现 im2col。代码如下: 1234567891011121314151617181920212223242526def conv2d_to_matmul(inputs, kernel, stride, padding, bias): # 保证 stride 和 kernel 的 size 相等 assert stride == kernel.shape[2] assert stride == kernel.shape[3] assert padding == 0 out...
llama.cpp Q 量化方式总结
llama.cpp Q 量化方式总结TheBloke 里有许多不同量化方式的模型,如下: 123456789CapybaraHermes-2.5-Mistral-7B-GGUF | - capybarahemers-2.5-mistral-7b.Q2_K.gguf | - capybarahemers-2.5-mistral-7b.Q3_K_L.gguf | - capybarahemers-2.5-mistral-7b.Q3_K_M.gguf | - capybarahemers-2.5-mistral-7b.Q3_K_S.gguf | - capybarahemers-2.5-mistral-7b.Q4_0.gguf | - capybarahemers-2.5-mistral-7b.Q4_K_M.gguf | - capybarahemers-2.5-mistral-7b.Q4_K_S.gguf | ... 它们都属于 llama.cpp 中 Q 量化定义的范围。llama.cpp 里的 Q 量化有两个格式:QX_Y 和 QX_K,第一种是对称量化和非对称...
MNN 自定义算子,以 AnyNet 为例
1. 介绍本文主要介绍如何在 MNN 中添加自定义算子,以 AnyNet 为例。AnyNet 添加了一个自定义算子,虽然可以用 pytorch 表达,并且导出 ONNX 和 MNN,但是节点过多,可视化工具无法很好的展示,因此本文尝试将 AnyNet 中的自定义算子添加到 MNN 中。 自定义 MNN 算子需要先将 pytorch 计算逻辑导出成 ONNX 节点,并且由 MNN 来解释。这需要首先将 pytorch 计算包装成 torch.autograd.Function,然后通过 torch.onnx.export 导出 ONNX 节点。然后通过 MNN 的 MNN::OpConverter 来解释 ONNX 节点。 2. AnyNet AnyNet 自定义了一个 SPNet 算子,并且使用 CUDA 实现了这个算子。SPN的结构,分为两种,分别是单路连接和三路连接: 实际上就是通过一个权重矩阵,上一个点迭代地给下一个点权重,对于单路连接和三路连接,有: $$\begin{align}h_{k,t} &= (1 - p_{k,t}) \cdot x_{k,...
Cosplay 视频转图片
Cosplay 视频转图片1. 介绍有很多时候 Cosplay 视频里的 Cosplayer 只有几个相同的画面,但是他们还是发出了一个短视频用于展示。我们想要把相同的画面剔除,对每个不同的画面保留一张图片。从信息论的角度来看,大部分 Cosplay 短视频的信息熵很低,只有几张图片是有意义的。这个项目就是为了尝试提取这些有意义的图片。 调研之后发现这是一个类似视频总结(Video Summarization)的问题。视频总结是一个很大的研究领域,有很多工作。这个项目只是一个简单的尝试,不会涉及到很多复杂的技术。 2. 方法受到 2401.04962v1 的启发,这个问题主要针对的是视频中的重复帧。我们可以通过计算每一帧的特征向量,然后通过聚类算法来找到相似的帧。这个项目使用了 K-means 算法来聚类。 2401.04962v1 的架构图如下: 这个工作将视频总结(Video summarization)工作分为了三个步骤: 使用 TransNetV2 对视频进行分割,得到单个短视频(shot),使用 CLIP 对每个短视频每一帧进行特征提取,得到每一个视频的特征描述...
powershell-autocomplete
Powershell 自动补全TODO: 编写 ADB 自动补全脚本,能够识别 ADB 设备并补全,类似 zsh 的补全体验 SSH 和 SCP 自动补全远程路径 从 Powershell Gallery 上使用 Install-Module 安装脚本之后,还需要使用 Import-Module 导入模块才能使用,如果希望自动加载,可以添加到 $PROFILE 中。
opencl-alloc-error
OpenCL Image 申请失败问题描述在使用 MNN 部署 ViT 的过程中,出现了这个报错: 1Alloc Image 3 x 49152 error, code:-40 解决方案这个问题是因为这个图像的尺寸超过了本设备 OpenCL 支持的最大尺寸,Adreno 630 的最大尺寸是 16384x16384,所以这个图像的尺寸 3x49152 超过了这个限制。这个尺寸出现的地方在 ViT 生成 QKV 的时候,这个尺寸是 768x2304,使用 RGBA 四通道 Image 时,reshape 之后的尺寸就是 3x49152。解决方案: 修改 MNN 的代码,将这个尺寸调整到小于 16384x16384。但是需要修改后续的计算代码 在导出模型时,不要将三个矩阵合并成一个矩阵进行计算,而是分开计算,这样就不会出现这个问题 Buffer 不会出错,可以使用 Buffer 代替 Image 进行计算,但是 MNN 没有自动 fallback 的功能,需要手动修改代码。设置 mode=72 (即 CPU 的线程参数),在 GPU 模式下它会被解释为使用 Buffer 格式还是...