mmap直挂模型权重:从30秒到1.2秒的底层原理与落地实践
做推理优化的朋友大概率见过这一幕同一个 70 亿参数的权重文件同事的脚本从启动到模型 ready 只要一秒出头而你的进程还在各种初始化日志里打转三十秒后才看到 first token。我第一次看到 1.2 秒这个数字时也不信直到把加载路径从“读文件-反序列化-再拷贝”换成“mmap 直挂权重”才发现绝大部分时间根本不用花。这是我这轮 30 天性能优化打卡 Day 3 的记录核心就回答一个问题mmap 直挂权重为什么能快到这个程度。这篇文章不会停留在调 API 层面我会把虚拟内存、page cache、零拷贝、缺页中断这些底层机制一次讲透再附上可以直接抄的落地步骤和踩坑记录适合正在做推理部署、模型加载优化或者只是好奇“14GB 权重怎么可能一秒加载完”的读者。1. 先算一笔账传统权重加载的时间都花在哪了1.1 一次“标准加载”的完整旅程先说传统加载方式。大多数老代码的路径是打开权重文件 - 读取全部字节 - 反序列化 - 逐张量拷贝到新内存 - 转换 dtype 或设备 - 释放临时对象。听起来没什么问题但每一步都在做“额外的事”。以一个 70 亿参数、半精度存储的模型为例权重文件大约 14GB。传统方式第一步就是把这个 14GB 从头到尾读进内存。假设 SSD 顺序读速度是 2GB/s纯读取理论上要 7 秒。这还只是“理论”实际文件系统元数据、碎片、以及读取过程中伴随的大量read系统调用都会让时间膨胀。接着是反序列化。很多旧格式本质上是“对象图重建”里面记录了每个张量的名字、shape、dtype、二进制内容还有各种嵌套结构。加载器要做的是解析协议、创建字典、为每个张量分配新内存、再把字节流复制进去。这一阶段是 CPU 密集型的14GB 数据流经 Python 层解析十几秒甚至几十秒都很正常。然后还有一次“看不见”的拷贝。原始字节 buffer 是一份内存反序列化出来的每个张量存储又是一份内存。14GB 权重意味着至少 28GB 的内存流量峰值内存占用可能达到权重的两到三倍。如果加载过程中还做了 dtype 转换比如从 fp32 转到 fp16那又是新的一份内存。所以传统方式慢不是因为某一个环节特别夸张而是每个环节都多做了一步。等这套流程走完30 秒就没了。1.2 三个最容易被忽略的隐形开销第一个是系统调用次数。文件越大read调用越多每一次read都是一次用户态和内核态的切换。虽然可以设计成大块读但很多框架为了边读边解析经常用小片 buffer 反复读系统调用开销被放大。而 mmap 直挂主流程只需要openmmapmunmap三次关键操作后续访问全部走内存指令。第二个是双倍内存带宽。普通read的数据路径是“磁盘 - 内核页缓存 - 用户态 buffer”每一字节至少经历两次内存搬移。14GB 的文件内存子系统实际搬运了 28GB 的数据。mmap 的数据路径是“磁盘 - 内核页缓存”应用直接访问页缓存省掉的恰好是“内核到用户态”那一次整块拷贝。这在大型权重文件上是非常可观的节省。第三个是反序列化和对象重建。旧式序列化协议要解释指令、构造对象、维护引用关系本质上是在执行一段“重建程序”。它没法利用“这块数据就在 offset 123456 处直接给我按 float16 解释”这种零拷贝思路。再加上安全校验、类型检查、设备迁移大量 CPU 周期都烧在了“把数据变成可用的张量”而不是“使用数据”本身上。我用一个生活类比帮你记住这件事普通加载像搬家先把所有东西从卡车上卸到临时仓库再一件件搬进新家还要拆开每个包装箱重新摆放mmap 直挂像是直接把新家的货架打通到卡车的车厢上你需要哪个箱子就现场开哪个没碰到的箱子根本不用卸货。2. mmap 为什么能快底层原理一次讲透2.1 虚拟内存、页表与缺页中断mmap 的全称是 memory map内存映射。它做的事情是把磁盘文件的一段区域直接映射到进程的虚拟地址空间里。映射完成之后你访问这段虚拟地址就像访问普通内存数组一样文件内容会自动出现在对应位置。这背后依赖的是虚拟内存机制。操作系统把物理内存和文件都切成固定大小的“页”进程看到的是连续的虚拟地址空间虚拟地址通过页表映射到物理页。当你mmap一个文件时内核并不是把文件内容复制到内存里而是修改进程的页表让一部分虚拟地址指向文件的页缓存。关键在缺页中断。如果某个页还没有真正读入内存访问它时 CPU 会触发缺页异常操作系统去磁盘把这一页读进 page cache更新页表然后让指令继续执行。这个过程对应用来说是透明的但带来了一个极其重要的特性按需加载。你没有访问的区域就永远不会被读进内存。这就是“直挂”二字的精髓。你在代码里用np.frombuffer或者框架提供的零拷贝 API 拿到权重视图时文件可能只被读入了几十个元数据页。真正触发大块磁盘读的是第一次前向传播访问到具体权重的时刻。2.2 从普通 read 到 mmap一次少搬一次家的过程对比一下两种方式的数据流动就清楚了。普通read磁盘控制器把数据 DMA 到内核页缓存然后 CPU 把页缓存里的数据再拷贝到用户态 buffer。这一步不光消耗内存带宽还会让 CPU 频繁参与大块数据搬移拖慢整个进程。mmap磁盘控制器把数据 DMA 到内核页缓存页表项直接指向这块物理页。应用访问虚拟地址时CPU 的 MMU 完成翻译数据不需要再从内核态拷贝到用户态。省掉的那一次拷贝就是大文件加载提速的第一个来源。还有一点经常被忽略mmap系统调用本身是 O(1) 的元数据操作它不读取文件内容。哪怕文件有 14GB建立映射也只需要几十毫秒。相比之下传统加载第一步的“整文件读入”是个 O(文件大小) 的阻塞操作等待时间完全躲不掉。2.3 page cache 让第二次访问更快操作系统内核有一个全局统一的页缓存最近读取过的文件页都会留在物理内存里。mmap 访问过的页自然也留在 page cache 中。这意味着什么第一次用 mmap 直挂权重加载了 1.2 秒如果权重文件没有变化进程退出后再启动一次很多页已经在 page cache 里第二次可能连 1 秒都不用。这在推理服务频繁发版、模型热升级场景下特别有用。而且文件页属于“干净页”内存紧张时内核可以随时回收不会造成永久占用。这跟普通read加载后应用自己在用户态分配的大块内存有本质区别。用户态分配的内存即使包含同样的数据也无法与其它进程共享多进程部署时每开一个 worker 就要多占一份内存。相比之下mmap 直挂的权重文件多个进程映射到同一文件时内核会复用同一批物理页。父进程加载权重后 fork 出若干 worker物理内存里权重始终只有一份。3. 实操把权重加载改成 mmap 直挂3.1 前置条件权重文件必须是“映射友好”的格式不是所有权重格式都能直接 mmap 直挂。想做零拷贝权重文件必须满足三个条件第一元数据和原始字节要分离。文件头部用 JSON 这种轻量格式描述每个张量的名称、dtype、shape、数据偏移量数据段则是一段连续的原始二进制。这样加载时只需要解析一个很小的 JSON 头剩下全部用偏移量定位。第二数据段要做对齐。每个张量的起始偏移量最好按 8 字节对齐。float16 只需要 2 字节对齐float32 需要 4 字节但为了省心统一按 8 字节对齐也方便将来扩展新的 dtype。第三不能用自包含的对象图协议。那种协议会把所有东西揉在一起加载器必须递归重建对象没法只靠“base pointer offset dtype”构造视图。社区里已经有不少零拷贝序列化设计思路基本都是我上面说的这套。如果你现在还是老格式建议先写一个转换脚本把权重导成“header json 二进制数据段”的布局这一步做完后面所有优化都会很顺。3.2 关键代码用 mmap 构造零拷贝权重视图下面用 Python 标准库 numpy 演示核心实现。文件布局假设为前 8 字节header 的字节长度无符号小端整数接下来 header_len 字节JSON 格式的元数据之后是原始权重数据数据段起始位置做 8 字节对齐import mmap import json import struct import os import numpy as np def load_weights_mmap(path): f open(path, rb) mm mmap.mmap(f.fileno(), 0, accessmmap.ACCESS_READ) f.close() # mm 建立后fd 可以关闭映射仍然有效 header_len struct.unpack(Q, mm[:8])[0] header json.loads(bytes(mm[8:8 header_len])) dtype_map { float16: np.float16, float32: np.float32, int8: np.int8, uint16: np.uint16, # bfloat16 在 numpy 里常用 uint16 承载 } data_start (8 header_len 7) ~7 views {} for name, meta in header[tensors].items(): dt dtype_map[meta[dtype]] shape meta[shape] offset data_start meta[data_offsets][0] # 数据段内偏移 count int(np.prod(shape)) arr np.frombuffer( mm, dtypedt, countcount, offsetoffset, ).reshape(shape) # 默认返回只读数组避免误写 arr.flags.writeable False views[name] arr return views, mm # 使用示例 views, mm load_weights_mmap(model_weights.bin) print(views[embedding].shape) # 直接得到可用的权重视图几个细节说一下mmap.mmap(fileno, 0, accessmmap.ACCESS_READ)里的0表示映射整个文件。映射建立后原始 fd 可以关掉不影响后续访问。np.frombuffer不会复制数据它直接在这段内存之上构造数组视图。这就是零拷贝的关键。对于 bfloat16numpy 没有原生的 bf16 dtype常用uint16先承载。之后在模型推理框架里把它 reinterpret 成 bf16 张量即可。如果只是做 CPU 推理这个views已经可以直接喂给模型如果要放到 GPU 上还需要一次显式设备拷贝那部分时间要单独算不属于“直挂权重建立视图”的开销。3.3 实测对比30 秒到 1.2 秒的钱花在哪下面是我在一个 70 亿参数半精度模型上做的对比两个路径的目标都是“模型在 CPU 侧 ready并且完成第一次前向所需的全部权重页加载”。阶段传统读取方式mmap 直挂方式打开文件0.1 秒0.02 秒全量读入 14GB约 7 秒不主动触发按需读页反序列化/解析头部15~25 秒约 0.1 秒仅 JSON构造张量5 秒分配拷贝0.05 秒视图零拷贝首次前向触发权重入内存无需额外等待已经全读进来了约 1.0 秒总计约 30 秒约 1.2 秒肯定有人会问14GB 文件就算按需加载1.2 秒也不可能全部读一遍。你说得对1.2 秒恰恰不是“全量读入”的时间而是“建立映射 解析头部 首次前向路径真正访问到的那部分权重页落入 page cache”的时间。语言模型推理第一个 token只会访问 embedding 和第一层 transformer block 等少量参数这部分可能就 1~2GB。按 2GB/s 的 SSD 顺序读速度读 1~2GB 理论上只需要 0.5~1 秒剩下的时间花在页表建立、JSON 解析和少量随机 IO 上合计 1.2 秒非常合理。如果你的场景是“必须把 14GB 权重全部拷贝到显存”那 1.2 秒肯定不够还要加上 PCIe 传输时间。mmap 直挂解决的是“从磁盘到可用视图”这一段不是 GPU 显存传输的银弹。3.4 更进一步多进程部署和大文件分片实际部署推理服务时经常是主进程加载模型然后 fork 出多个 worker。传统方式下每个 worker 都会各自保存一份权重拷贝内存占用直接乘以 worker 数。mmap 直挂后所有子进程共享同一份文件页的物理内存权重在 RAM 里只有一份内存收益是实打实的。如果做模型并行还可以把权重文件按层或按分片组织每个 rank 只映射自己需要的那一段偏移不需要把完整文件都映射进来。这样不但省内存还能减少首次访问的磁盘 IO。映射区间的起始偏移只要按页对齐即可数据段内部不要求页对齐因为 mmap 本身是以页为粒度管理的文件内部偏移不受限制。有一个实操建议导出权重时尽量按推理的访问顺序排列张量把 embedding、第一层 transformer 放在文件前面后面的层按顺序往后排。这样按需加载时的磁盘读基本是顺序读首次访问速度会非常漂亮。如果顺序混乱首次 forward 会触发大量随机读1.2 秒可能膨胀到十几秒。4. 常见问题与排查技巧4.1 文件被截断为什么访问映射区会直接崩mmap 映射后如果你访问的页在文件里不存在进程会收到 SIGBUS 信号直接段错误。这个错误用 try/except 救不回来因为它不是 Python 异常而是硬件层触发的信号。最典型的场景是加载权重时另一个进程正在覆盖写这个文件导致文件尺寸变短或者文件下载只下了一半就被启动脚本拉起。排查办法是在 mmap 之前先校验文件大小和元数据声明的总字节数expected_size 8 header_len header[total_bytes] if os.path.getsize(path) expected_size: raise ValueError(fweight file size mismatch: {path})这个校验必须放在 mmap 之前而且要放在反序列化 JSON 之后。等进程跑到一半才崩排查成本会高很多。4.2 冷启动还是慢提前预热 page cache有读者私信问过为什么第一次起服务要 8 秒第二次起服务只要 0.5 秒。这完全正常第一次访问权重页时磁盘读取躲不掉。如果想让冷启动更稳定可以在发版脚本里做一次文件预热让工作集提前进入 page cache。最简单的预热命令是把文件读一遍并丢弃cat weights.bin /dev/null也可以用系统提供的文件预读接口告诉内核“我马上要顺序访问全文件”内核会做更积极的预读比盲目 cat 更准确。预读之后服务进程真正 mmap 时大部分页已经驻留内存1.2 秒还能再压一截。这个技巧尤其适合容器重启后、第一次健康检查超时场景。4.3 fork 之后共享和写时复制的关系父进程先 mmap 权重再 fork 子进程子进程会继承相同的映射。只要没人写这些页所有子进程指向同一份物理页内存共享。一旦某个子进程写了某个页就会触发写时复制在内核里复制一份独立物理页。问题在于权重张量一旦被某个 worker 误写轻则触发复制导致内存浪费重则直接污染该 worker 的数据视图。我在代码示例里特意把arr.flags.writeable False打开就是这个原因。Python 的 mmap 使用ACCESS_READ时numpy 写入会报 BufferError但如果在 C 扩展层面绕过检查强行写仍然可能踩到 SIGSEGV。所以规范做法是只读映射 只读视图 代码审查里明确“权重对象禁止原地修改”。4.4 物理内存不足madvise 和 swap 抖动页面缓存虽然可回收但如果物理内存本身不够访问映射页时可能出现频繁换入换出表现为服务忽快忽慢。排查时重点关注系统的 cached 和 swap 指标cached 里都是文件页如果在频繁下降又上升说明内存压力很大正在反复回收和重读。对权重加载场景可以给内核一点指导。比如一句话生成服务访问权重页的规律接近“按顺序流式读取”可以用顺序预读提示如果模型结构导致访问模式很跳跃又不想让内核浪费预读 IO可以用随机访问提示。madvise 的调用在 Python 里可以通过ctypes或专门的绑定库完成不复杂但值得单独封装一个函数。要注意madvise 只是提示不是保证。在内存严重不足时内核仍然可能丢弃这些页。真正要紧的是把部署机的内存配够让“模型工作集 运行时内存”在常态下留有 20% 以上余量。这个余量不仅是给 page cache 的也是给突发请求的。4.5 数据对齐和大小端两个容易踩的边角问题np.frombuffer对对齐有要求。如果数据段的起始偏移不满足 dtype 对齐比如 float32 数组从一个奇数地址开始numpy 会直接报错。所以我在文件布局里强制把数据段起始位置对齐到 8 字节一步到位。大小端问题则更隐蔽。现在绝大多数服务器是小端机器训练出来的权重也按小端存。但如果你的权重来自某些嵌入式或特殊硬件平台可能带着大端数据。加载后第一眼看不出问题数值全乱。建议在转换导出阶段就把字节序统一成小端宁可转换时花一次时间也不要让每个部署环境都处理一遍字节序分支。通过这一轮实操我最大的体会是mmap 直挂权重并不是一个花哨技巧它就是操作系统本来就该做好的事——按需加载、共享物理页、减少无意义拷贝。真正需要你做的是先把权重文件整理成适合映射的布局然后把加载逻辑从“读文件 反序列化 拷张量”简化成“取偏移 建视图”。最后再分享一个小技巧如果你在容器里频繁重启服务可以把权重文件单独放到一个固定的磁盘路径发版时确保文件内容不变这样 page cache 的重用率会高很多1.2 秒这个数字还能继续往下降。

相关新闻

AI日报制作全流程:信息筛选、内容写作与效率优化实战

AI日报制作全流程:信息筛选、内容写作与效率优化实战

1. 一份“AI日报”到底在记录什么每天早上花十五分钟翻一遍行业动态,把值得关注的信息筛出来、理清楚、写明白,这件事我坚持了快两年。很多人觉得“日报”就是流水账,把新闻标题复制粘贴一遍完事,但真正做过内容的人知道&#xff…

2026/10/13 2:16:27 阅读更多 →
Label Studio:两条 Docker 命令完成第一次数据标注并导出模型训练格式

Label Studio:两条 Docker 命令完成第一次数据标注并导出模型训练格式

Label Studio:两条 Docker 命令完成第一次数据标注并导出模型训练格式 【免费下载链接】label-studio Label Studio is a multi-type data labeling and annotation tool with standardized output format 项目地址: https://gitcode.com/GitHub_Trending/la/labe…

2026/10/13 2:15:26 阅读更多 →
Gemini cli 源码分析之工具篇:ReadFile 工具从入口到落盘的完整链路拆解

Gemini cli 源码分析之工具篇:ReadFile 工具从入口到落盘的完整链路拆解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 2:15:26 阅读更多 →

最新新闻

Mathesar 0.5.0 版本详解:表单构建器、记录查看体验与安装流程的全面升级

Mathesar 0.5.0 版本详解:表单构建器、记录查看体验与安装流程的全面升级

数据库后端前端协作 【免费下载链接】mathesar An intuitive spreadsheet-like interface that lets users of all technical skill levels view, edit, query, and collaborate on Postgres data directly. 100% open source and self hosted, with native Postgres access co…

2026/10/13 2:56:40 阅读更多 →
把 79 个数据工具塞进一个 Python 脚本,再用 n8n 排成日更流水线:TaoToken 统一 Key 接入实践

把 79 个数据工具塞进一个 Python 脚本,再用 n8n 排成日更流水线:TaoToken 统一 Key 接入实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 2:56:40 阅读更多 →
OpenSpiel 中的 Hive 棋实现:面向 AlphaZero 的六边形棋盘建模、UHP 协议与动作空间设计

OpenSpiel 中的 Hive 棋实现:面向 AlphaZero 的六边形棋盘建模、UHP 协议与动作空间设计

人工智能强化学习深度学习 【免费下载链接】open_spiel OpenSpiel is a collection of environments and algorithms for research in general reinforcement learning and search/planning in games. 项目地址: https://gitcode.com/gh_mirrors/op/open_spiel 点击…

2026/10/13 2:56:40 阅读更多 →
Ask Dr. Andrew Huberman 系统提示词深度解析:TheBigPromptLibrary 中神经科学人物模拟 GPT 的指令设计

Ask Dr. Andrew Huberman 系统提示词深度解析:TheBigPromptLibrary 中神经科学人物模拟 GPT 的指令设计

提示工程AI 安全治理 【免费下载链接】TheBigPromptLibrary A collection of prompts, system prompts and LLM instructions 项目地址: https://gitcode.com/gh_mirrors/th/TheBigPromptLibrary 点击查看 免费下载 本篇技术指南围绕 TheBigPromptLibrary 仓库中收…

2026/10/13 2:56:40 阅读更多 →
C#反编译实战:从dll/exe还原可编译源码的完整流程与避坑

C#反编译实战:从dll/exe还原可编译源码的完整流程与避坑

简介:这份C#反编译工具包面向需要查看、分析和理解.NET程序集内部结构的开发者,适用于代码逆向、调试排错和技术学习等场景。压缩包共16个文件,大小2.19MB,以dll、exe、txt、rtf等类型为主,其中包含RedGate Reflector及…

2026/10/13 2:56:40 阅读更多 →
Bresenham画圆算法:整数微分与八分对称的嵌入式图形实现

Bresenham画圆算法:整数微分与八分对称的嵌入式图形实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 2:55:39 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →