显存去哪了?深度学习框架显存管理机制与多模型共存指南
在使用 MinerU、Stable Diffusion 或 LLM 本地部署时,我们经常会遇到一种“灵异现象”:模型明明跑完了,任务也结束了,但显存(VRAM)占用依然居高不下。如果有两个模型想在同一张显卡上轮流跑,经常会因为前一个模型“占着茅坑不拉屎”而导致后一个模型 OOM(Out Of Memory)。 为什么显存会“无休止”地扩张?为什么框架不愿意把显存还给操作系统?这背后其实是一套精心设计的“贪婪”机制。 今天我们就来扒一扒深度学习框架(以 PyTorch 为例,TensorFlow 同理)的显存管理底层逻辑,以及如何在单卡上优雅地运行多个模型。 一、 为什么显存“只吃不吐”?很多开发者会发现,Python 脚本运行过程中,显存占用往往是一条只增不减的曲线。这其实是因为框架内部实现了一个 Caching Allocator(缓存分配器)。 1. 昂贵的系统调用在 GPU 上分配内存(cudaMalloc)和释放内存(cudaFree)是系统级调用,这些操作非常“昂贵”,会强制 GPU 同步,打断计算流水线。 如果模型在推理过程中,每算一层网络就申请一次显存,算完就释放...
开发安全指北:ORM 防住了 SQL 注入,那“文件名注入”呢?
在现代 Web 开发中,ORM(对象关系映射)框架的普及极大地降低了 SQL 注入的风险。很多开发者(包括以前的我)因此产生了一种错觉:“只要我用了 SQLAlchemy 或 Django ORM,我的后端就是安全的。” 然而,现实往往会给你一记响亮的耳光。最近我在做安全排查时被告知存在“文件注入”和“文件名注入”风险。这让我意识到,Web 安全远不止 SQL 注入那么简单。 今天我们就来聊聊,除了 SQL 注入,开发过程中还有哪些容易被忽视的“注入”陷阱,以及我们该如何防御。 一、 文件名注入与路径遍历 (Path Traversal)这是很多初级甚至中级开发者最容易踩的坑。 1. 场景还原假设你有一个上传头像的功能,后端代码可能是这样写的: 1234567import osdef upload_avatar(file): # 直接使用用户上传的文件名 filename = file.filename save_path = os.path.join('/var/www/uploads', filename) file.save(...
SQLAlchemy 踩坑:我只想复制一张表,却意外触发了“联表继承”
在 Python 后端开发中,我们经常使用 SQLAlchemy 作为 ORM 框架。最近在做项目时,我遇到了一件非常有意思的事情,或者说是一个“经典的误解”。 事情是这样的:我有一个现成的文件表 File,它的结构定义得很完美。随着业务发展,我需要创建一个备份表 BackupFile,要求它的结构跟 File 表 完全一致。 作为一个崇尚 DRY (Don’t Repeat Yourself) 原则的程序员,我的第一反应当然是——继承! 于是我写出了类似这样的代码: 123456789101112131415from sqlalchemy import Column, Integer, String, ForeignKeyfrom sqlalchemy.orm import declarative_baseBase = declarative_base()class File(Base): __tablename__ = 'file' id = Column(Integer, primary_key=True) filename = Col...
工具-MinerU高显存占用解决方案
在文档智能处理(Document AI)领域,MinerU 是一款强大的开源 PDF 解析工具,能够精准提取文档中的 Markdown 内容、公式和表格。然而,在实际工程落地中,直接将几百页的 PDF 扔给模型处理,往往会面临一个棘手的问题——显存(VRAM)爆炸。 本文将结合一段 Python 实战代码,深入剖析为什么大文件会导致显存溢出,并阐述一种基于“单页拆分”的优化策略及其背后的原理。 1. 痛点:为什么大文件会让显存“烟花”?MinerU(以及大多数基于 Transformer 或视觉编码器的模型)在处理文档时,需要将输入内容转换为高维向量表示。要回答“为什么拆分后显存就不炸了”,我们需要深入到深度学习模型的显存占用机制。 1.1 显存都去哪儿了?在深度学习推理(Inference)过程中,显存主要被以下几部分占用: 模型权重(Model Weights):这是固定的。不管你输入是一个字还是一万个字,加载模型本身(如 InternVL、LayoutLM 等)就需要占用几个 GB 的显存。这部分是“入场费”。 中间激活值(Activations)与临时缓冲区:这是显存...
docker-如何在容器中映射字体
拒绝“豆腐块”:Docker 容器化部署中的 Matplotlib 中文显示在 Python 数据可视化的世界里,Matplotlib 无疑是王者。然而,当将那个在本地跑得完美的脚本打包进 Docker 容器并部署到服务器上时,往往会遭遇当头一棒:生成的图表中,原本优雅的中文标题变成了满屏的方框(俗称“豆腐块”)。 现在从一段生产环境的代码出发,探讨为什么 Docker 会“吃掉”字体,以及一种简单粗暴却极度有效的解决方案——本地字体映射。 1. 案发现场:代码解析让我们看看 utils/create_pie.py 中的关键片段: 1234567891011121314151617import osimport matplotlib.pyplot as pltfrom matplotlib.font_manager import FontPropertiesfrom config import setting# 关键点 1:明确指定字体文件的绝对路径font_path = os.path.join(setting.FONT_DIR, 'SourceHanSerifSC-...
Docker部署Gitea服务:轻量级Git仓库的搭建与迁移指南
前言在日常开发中,我们经常需要一个私有的Git仓库服务来托管代码。虽然GitHub和Gitee都非常好用,但有时候出于数据隐私、网络速度或者完全掌控的需要,自建一个Git服务是很有必要的。 考虑到你可能面临服务器到期更换服务商的情况,数据的便携性和迁移的便利性成为了核心需求。同时,你也希望平台能完美支持中文。 综合这些需求,Gitea 是一个绝佳的选择。它是一个开源的、轻量级的Git服务,使用Go语言编写,运行速度快,资源占用低,且完美支持Docker部署。最重要的是,它的数据结构非常简单,迁移起来只需要打包几个目录即可。 本文将手把手教你如何使用Docker部署Gitea,并演示如何进行数据的备份与迁移。 环境准备在开始之前,请确保你的服务器已经安装了Docker和Docker Compose。 针对中国大陆用户的特别提示:由于网络原因,直接从Docker Hub拉取镜像可能会很慢甚至失败。建议配置国内的Docker镜像加速器。 编辑 /etc/docker/daemon.json (如果不存在则创建),添加如下配置(使用国内常见的加速源): 1234567{ &...
Python类型注解:让动态语言更稳健
Python类型注解:让动态语言更稳健 动态一时爽,一直动态一直爽?但类型注解能让你的Python代码更清晰、更易维护。 Python作为一门动态类型语言,以其灵活性和易用性深受开发者喜爱。然而这种动态性是一把双刃剑——随着项目规模扩大,代码的复杂度和维护成本也随之增加。类型注解(Type Hints)正是为了解决这些问题而引入的重要特性。 一、为什么需要类型注解1.1 动态类型的代价Python的动态类型特性意味着变量类型在运行时才确定,这带来了极大的灵活性: 1234a = 10print(a) # 输出:10a = "Python" print(a) # 输出:Python 这样的灵活性在小项目中非常方便,但在大型项目或团队协作中却带来了问题: 代码可读性差:很难直接从代码中看出变量或函数的预期类型 维护困难:几个月后回头看自己的代码,甚至作者本人也可能忘记变量的预期类型 调试成本高:类型错误往往在运行时才被发现 1.2 类型注解的解决方案Python 3.5引入了类型注解(PEP 484),它允许开发者明确标注变量、函数参数和返回值的类型...
Docker管理工具对比:Portainer与Dockge的定位与抉择
Docker管理工具对比:Portainer 与 Dockge 的定位与抉择在Docker容器化部署的生态中,高效的管理工具至关重要。Portainer和Dockge是两款备受关注的图形化管理界面,它们设计理念不同,各有侧重。本文将从六个核心维度对两者进行客观对比,以帮助您根据实际场景做出选择。 一、 核心定位与设计哲学 Portainer:一款功能全面的企业级Docker管理平台。它提供了从容器、镜像、网络、卷到用户权限和集群管理的全方位控制,适合需要复杂管理和团队协作的场景。 Dockge:一款轻量、专注的Docker Compose文件管理器。它的核心目标是让通过docker-compose.yml文件部署和管理应用栈变得简单直观,非常适合习惯“代码即基础设施”理念的单一用户或小型环境。 二、 六大功能维度对比1. 单容器部署与管理 Portainer胜出:对于快速部署、测试单个容器(如Grocy、Heimdall等),Portainer提供了极大的便利。通过图形化按钮即可完成容器状态控制、一键复制、添加健康检查等操作,无需手动编写配置文件,适合快速实验和摸索。 Doc...
OAuth:一场“授权”而非“坦白”的安全舞会
OAuth:一场“授权”而非“坦白”的安全舞会想象一下这个场景:你新装了一款精美的个人记账软件(我们叫它“小账本”),它告诉你:“我能帮你自动分析你的银行消费,让你理财更轻松!” 你心动了,但问题来了:要让它分析你的银行账单,你是不是得把自己的银行账号和密码直接告诉“小账本”? 停!快打消这个危险的念头! 这就像你把家里的钥匙交给一个陌生的管家。即使他心地善良,万一他保管不善,钥匙被复制了怎么办?你永远不应该把自己的主密码(尤其是银行密码)交给任何第三方。 那么,如何安全地让“小账本”只读取你的银行交易记录,而又不暴露你的密码呢? 这就是 OAuth 要解决的世纪难题。它诞生于2007年的Twitter,核心目标就是:让第三方应用能在“不拿到用户密码”的前提下,获得有限的访问权限。 一、 OAuth 的核心思想:从“交钥匙”到“发门禁卡”我们可以用一个简单的比喻来理解: 坏方法(交钥匙):你把银行保险库的主钥匙(密码) 给了“小账本”。它能进去,但也能做任何事,甚至修改你的账户信息,风险极高。 好方法(OAuth发门禁卡):银行大堂经理(授权服务器)给你一张特殊的门禁卡(Acc...
Elasticsearch从来都不是数据库
Elasticsearch 从来都不是数据库:一个被“滥用”的神级搜索引擎 本文核心观点源自 James Blackwood-Sewell 的博客,经深度梳理与重构,以更契合中文技术阅读习惯的方式呈现。 在我们开始之前,请先回答一个简单的问题:你团队里的 Elasticsearch(后文简称 ES),主要被用来做什么? 如果你的答案是“全文搜索”,那么恭喜,你正在正确地使用它。但如果你的答案是“作为我们应用的主数据库”,那么这篇文章或许能帮你避开许多未来注定要踩的坑。 一、 引言:被混淆的“身份”Elasticsearch 从来都不是一个数据库。 它的本质,是在 Apache Lucene 这个强大的全文搜索库之上构建的搜索引擎 API。它生来就是为了解决“搜索”问题,而非作为记录的系统(System of Record)。 甚至 Elastic 官方指南也长期建议:你的事实来源(Source of Truth) 应该放在别处(如 PostgreSQL、MySQL),而 ES 只应作为二级索引存在。 然而,在过去十年中,无数团队在尝到搜索的甜头后,开始尝试将这颗“糖衣炮弹”扩展...














