让有限显存扛住更多并发:KV Cache 调度与加速引擎详解

最近一直在折腾多智能体框架,组里有人用那个叫 OpenClaw 的开源项目跑了一周,GPU 显存肉眼可见地被吃掉,直接把一台 80G 的卡干到 OOM。群里有人嘴快,说 OpenClaw 这下真成“吞金龙虾”了——又贵又能吃,还得给它剥壳。这梗虽然好笑,但问题是真的:LLM 推理的长上下文场景里,KV Cache 不去管,再大的显存也不够造。

这也是我今天想认真聊聊百舸平台这套 KV Cache 调度与加速引擎的原因。它不是一个单独的“显存优化技巧”,而是一整套把 KV Cache 从“被动缓存”变成“主动调度资源”的方案。适合谁看?正在做 Agent 应用、需要处理超长上下文、或者被在线推理显存成本压得头疼的开发者。这篇文章我会从问题本质讲起,把它的设计思路、核心机制、接入方式和踩坑经验都拆开来说。

1. 先从“吞金龙虾”说起:KV Cache 到底吃掉了什么

1.1 没有 KV Cache 的 LLM 推理有多笨

要理解 KV Cache 为什么重要,得先看看大模型在“说话”的时候干了什么。模型做推理是逐 token 生成,每生成一个 token,都要拿着“前面所有 token 的隐藏状态”过一遍注意力层。问题是,如果不做任何缓存,每走一步都要把前面所有 token 的 Key 和 Value 重新算一遍,这笔账算下来非常夸张。

举个例子,一个 12 层、隐藏维度 768 的模型,输入上下文 4000 token,每一个 token 每层都要产出 Key 和 Value,两个矩阵,FP16 精度下每个元素占 2 字节。粗算一下:每 token 的 KV 开销大概等于 2 × 层数 × 隐藏维度 × 2 字节,也就是 2 × 12 × 768 × 2 ≈ 36KB。4000 token 的上下文,KV Cache 就大概占 147MB。这还只是单条请求,如果并发 10 路,直接就是 1.4GB 起步。

没有 KV Cache,意味着每生成一个新 token,这些计算全部重来,显存和算力都在做无用功,延迟也会被无限拉长。所以实际工程里,“把已经算好的 KV 存下来复用”几乎是必然选择,这就是 KV Cache 存在的根本原因。

1.2 Agent 场景为什么是 KV Cache 的“重灾区”

单轮对话的 KV Cache 开销已经是负担,但多智能体框架更夸张。OpenClaw 这类 Agent 项目有四个特点,每个特点都在往 KV Cache 上狠狠加码:

  • 长上下文:Agent 要把系统提示词、历史对话、工具调用记录、检索到的文档片段全部拼进一个上下文窗口,动辄几万 token 起步;
  • 多轮工具调用:每调一次工具,结果文本重新拼回上下文,新 key 继续增长;
  • 并发密集:多个 Agent 并行跑任务,共享同一批 GPU,KV Cache 总量直接翻倍再翻倍;
  • 重复前缀:所有 Agent 的系统提示词几乎一样,工具 schema 也差不多,这些内容每来一条请求就要算一遍。

所以你会发现,Agent 场景里 KV Cache 不只是“挺占地方”,而是整个推理链路里最大的显存黑洞。组里那台 80G 卡被吃爆,就是因为 16 路 Agent 并发,加上每个任务的上下文都超过 20K,KVCache 计算下来早就超过了可用显存。

1.3 只做“缓存”远远不够,问题出在调度

传统做法是给 KV Cache 上淘汰策略,比如不够了就 LRU 踢掉,再不够就量化压缩。但多智能体场景下,KV Cache 的形态和访问模式比“单轮对话缓存”复杂得多:前缀高度重复、但后续内容各自分叉;工具执行结果可能过期、缓存复用的准确性会直接决定输出质量。

这些问题说明,KV Cache 不能只被当成一块“存了就能少算”的缓存区,它更像是推理集群里的“高速缓存层”,必须通过调度策略统一管理,知道什么该存、存多久、放内存还是磁盘、哪些请求该路由到哪台机器。百舸这套 KV Cache 调度与加速引擎,本质上是把 KV Cache 做成了一等公民的调度资源,而不是顺带的优化项。

2. 设计思路拆解:把 KV Cache 当作“显存中的热点数据分层”

2.1 核心出发点:Cache 也要讲“命中率”

其实 KV Cache 调度和操作系统里的页面调度特别像。操作系统不会把所有页面都塞在内存里,而是分热页、冷页,热页留在内存,冷页换到磁盘。百舸引擎的思路也一样,把 KV Cache 按访问频率、复用价值、时效性分成多层,让热点 KV 块留在 GPU 显存的高速区,冷点落到 CPU 内存甚至磁盘,最大程度提升有限显存里的缓存命中率。

在这个体系下,“一条请求来了先去查缓存有没有现成 KV”是标准路径。如果前缀命中,就直接把缓存的 KV 块拼进来,从最后一个未命中位置开始继续算,省掉前面所有 token 的预填充时间。这比单纯扩大显存划算得多,因为 Agent 请求的系统提示词、知识库内容来回就那些。

我自己在测试环境里试过一个场景:40 条并发请求,共享同一套系统提示词和 5 份固定知识库文档,上下文长度大约 16K。如果没有缓存复用,每条请求都要从头开始预填充 16K 的 KV;打开前缀复用后,相同的前缀部分直接命中缓存,实际只有每条请求里不同的那几百 token 需要重新计算,效果立竿见影。

2.2 块级调度,而不是整个 Cache 一刀切

百舸引擎里有一个关键设计:KV Cache 不是按“整条会话”来管理的,而是按固定大小的“块”为单位。这个思路和分页技术一脉相承,每条会话的 KV 序列被切成 16、32 或 64 个 token 一组的块,块与块之间可以独立分配、释放、搬运。

为什么这样做?因为整条会话的 KV Cache 是一个大序列,直接整体缓存有两个致命问题。一个是空间碎片化:长会话被中断、淘汰一部分内容后,剩余的空间不一定能拼给新请求使用;另一个是复用粒度太粗:新请求和缓存会话往往只有前半部分重叠,如果必须整条命中才能复用,那绝大多数情况都命中不了。

块级调度解决了这两个问题。新请求到达时,引擎先按前缀逐块比,相同的块直接复用地址,不同的块才重新分配显存。多个请求之间可以共享同一个前缀块,物理显存里只保留一份数据,靠共享引用计数维护生命周期。这种“多个虚拟会话共享物理 KV 块副本”的机制,是整套引擎能把显存利用率拉高的核心。

2.3 路由调度与缓存亲和性

调度引擎还有一层比较容易被忽视的设计:请求路由的缓存亲和性。多机多副本部署时,同一个用户、同一个 Agent 任务的连续请求,如果被负载均衡打散到不同的机器上,那每台机器的 KV Cache 都无法复用,等于缓存全部失效。百舸的调度层会把“携带相同前缀特征”的请求优先路由到同一组 GPU 上,保证热 KV 块始终留在原地的显存中。

这个策略有点类似 Web 场景里的会话粘滞。效果上也确实如此,我做过对比:关闭亲和路由时,前缀命中率只有不到 20%,打开后直接拉升到 60% 以上。所以,缓存调度不能只盯“缓存内部怎么做”,外部流量怎么进也是决定命中率的一半。

3. 核心机制深挖:哈希索引、热点识别与淘汰策略

3.1 KV 块哈希索引与“前缀树”复用

块级复用怎么知道哪些块是相同的?答案是对每个 KV 块算哈希。引擎在收到请求时,把所有输入 token 切成固定长度的块,对每个块做哈希签名,用哈希值去查全局索引表。查询命中某个块,就说明这块内容之前已经算过 KV,直接把对应的 KV 块地址挂到当前会话上即可。

这里说一下哈希的粒度问题。如果以“文本内容”做哈希,会有一个坑:同一个文本,示例中如果 token 化之后的边界有细微差别,哈希就对不上。稳妥做法是对“token 序列”而不是“字符串内容”做哈希,因为 KV Cache 本身依赖的是 token 层面的 Key/Value,token 序列一致,KV 计算结果才会一致。

另外,块与块之间不是孤立存在,而是天然形成“前缀结构”。引擎会把命中块构造成一棵共享前缀树,同一根树干下挂着多条分支会话。当新请求走到某个已经存在的分支节点,就直接接管节点下已缓存的 KV 块,不需要重新计算;只有从分叉点往后的未命中块,才进入正常的预填充流程。

3.2 热点识别:谁是真正值得留在显存的缓存块

缓存空间有限,不能所有块一视同仁。百舸引擎里有一个热点识别模块,实时统计每个 KV 块的访问频次、最近访问时间、块大小和所属会话的重要程度,最终给每个块打一个“保留价值”分数。

这个分数和访问频率正相关,但也加入了一个很关键的“共享度”指标。一个块如果同时被 20 条会话引用,它的淘汰成本极高,哪怕访问频次暂时不高,也应该留在显存。相对的,一条只有单一会话在用的长尾块,再久没访问很容易被回收。我理解这种思路的核心是:KV Cache 调度的目标不是“缓存最热的内容”,而是“让淘汰任何一个块造成的重计算成本最高”。

3.3 淘汰策略:不只是 LRU,而是综合代价模型

提到 KV 缓存淘汰,很多人第一反应是 LRU(最近最少使用)。但 Agent 场景下纯 LRU 会有明显问题:一个包含大量共享工具描述的前缀块,可能因为某一段时间没有 Agent 新请求命中,被 LRU 判定为冷数据淘汰掉;等下一波请求高峰期来临,所有 Agent 又要重新计算这块 KV,直接导致预填充风暴。

所以百舸引擎采用的是一个综合代价模型,核心有两个维度:块未来的命中期望和块被淘汰后的重建成本。命中期望由近期访问频率和时间衰减拟合,重建成本由块长度和共享会话数量决定。一个“短而多人共享”的块,淘汰成本比“长而单会话”的块高得多,所以前者会优先保留。这套策略在某些极端场景下,比纯 LRU 能多保住 30% 以上的有效命中。

3.4 KV 量化压缩:让单卡塞下更多缓存块

调度做得再好,显存的物理上限还是卡在那。百舸引擎内置了 KV Cache 的量化压缩选项,默认支持 FP16、INT8、INT4 几档。如果走 INT8 量化,KV Cache 体积直接减半,INT4 可以压到四分之一。代价是精度损失,因此引擎内部会按块做敏感性分析,对注意力得分影响大的块用高精度保存,对影响小的块才压缩。

工程实践里,我建议 KV 量化不要无脑开满。上下文长度超过 32K 的 Agent 场景,INT4 量化后模型输出的连贯性和工具调用准确率会有轻微下降,INT8 则几乎无损。所以比较稳妥的策略是:热块区域用 FP16 或 INT8,冷块区域用 INT4,混合精度才能兼顾显存和效果。

4. 实操接入:如何把 KV Cache 调度引擎用起来

4.1 接入点选在哪里最合适

调度引擎不是一个独立的大模型推理服务,它更像一层嵌入在推理框架之上的 KV 管理中间层。接入的第一件事,是找到推理链路里合适的位置:需要在 token 序列进入模型前做拦截,在预填充阶段同步做块划分和哈希查询,在后面解码阶段管理和释放 KV 块。

以某开源推理框架为参考,接入过程大致分四步:第一,在请求入口增加一个分块器,把 prompt token 序列按 block_size 切块;第二,每块用哈希模块计算签名,到全局索引里查缓存;第三,把命中块的 KV 地址拼入显存管理器的页表;第四,为未命中块走正常推理路径,并把新生成的 KV 块同步写回缓存索引。

实际开发中,前两步是最容易出问题的,后面两步反而在框架层都是现成接口。

4.2 关键参数调优:block_size、缓存上限与淘汰阈值

这里分享几个我在调优过程中反复试出来的参数经验。

block_size 是最关键的一个参数,它决定了块复用的“颗粒度”。设得太大,比如 128 token 一块,共享前缀只要有一个 token 不同,整个块就无法复用,白白浪费;设得太小,比如 8 token 一块,哈希索引条目数量爆炸,索引查询本身就成了新的性能瓶颈。大多数场景下,32 token 是一个不错的起点,兼顾命中率和索引开销之间的平衡。

缓存上限(cache_capacity)建议设置为“模型最大 KV 显存容量的 1.5 倍”。这个数听起来反直觉,因为 KV 显存容量是模型和上下文长度决定的物理上限,缓存超出上限怎么办?实际上,调度引擎会在 CPU 内存里建一层二级缓存空间,只是访问速度比 GPU 显存慢得多。多出来的 0.5 倍,就是给 CPU 冷缓存预留的。

淘汰阈值没有固定值,而是调试出来的。我自己的经验是,观察命中率的曲线:如果命中率长期低于 30%,先别急着调淘汰策略,优先检查路由亲和性;如果命中率在 30% 到 50% 之间波动,调高“重建成本”在淘汰评分中的权重,效果最明显。

4.3 一个最小可用的接入伪代码

为了让前面的思路更直观,我写一段精简版的接入逻辑,放在任何支持钩子机制的推理框架里都可以跑通:

class KVCacheBlock: def __init__(self, block_hash, kv_pointers, ref_count): self.block_hash = block_hash self.kv_pointers = kv_pointers self.ref_count = ref_count self.last_access = time.time() class KVEngine: def __init__(self): self.index = {} self.blocks = {} def split_and_hash(self, token_ids, block_size=32): blocks = [] for i in range(0, len(token_ids), block_size): block = token_ids[i : i + block_size] block_hash = hash(tuple(block)) blocks.append(block_hash) return blocks def query(self, token_ids): block_hashes = self.split_and_hash(token_ids) hit_begin = 0 for h in block_hashes: if h not in self.index: break hit_begin += 1 return block_hashes, hit_begin def commit(self, block_hashes, kv_cache): for h in block_hashes: if h not in self.index: kv_block = KVCacheBlock(h, kv_cache, 1) self.index[h] = kv_block

简单解释一下逻辑:query()返回的是“前缀里命中了多少个块”,拿到hit_begin之后,推理框架从hit_begin对应的 token 位置开始做预填充;commit()是把新计算的 KV 块登记进索引,后面相同内容的请求就能直接复用。实际生产版本远比这段复杂,但核心骨架大体就是这么回事。

5. 实测效果与典型问题排查经验

5.1 一组可复现的压测收益

我在一个模拟 Agent 调度系统里做了几轮对比测试,配置是按百舸引擎的思路手工模拟的。模型上下文窗口 32K,压测场景是 20 路 Agent 并发,每路携带 8K 共享系统提示词 + 16K 独立任务上下文,生成长度 2K。

关闭 KV 缓存调度时,GPU 显存峰值直接卡到 92% 左右,20 路由 4 张卡分担都吃力;开启块级复用之后,共享的 8K 提示词只算一次,16K 独立上下文才是每路真正占用的部分,显存峰值降到大约 60%,同等显存下可以多扛 12 路左右的并发。

延迟上的变化也很直观。没有缓存复用时,每路请求的平均首 token 延迟大约 3.8 秒,因为大部分时间都耗在共享前缀的预填充上;启用调度后,首 token 延迟降到 1.4 秒,后面单路生成的速度受显存释放的正面影响也有 15% 左右的提升。当然,这个数据在不同模型、不同并发模型下会有差异,但趋势非常一致。

5.2 问题一:缓存命中率上不去

这是接入后最先遇到的问题。命中率低通常不是淘汰策略的锅,而是请求文本串不齐。最常见的原因是系统提示词里带了动态字段,比如时间戳、随机数、用户 ID。某同事接入时,系统提示词末尾拼了个当前时间,结果每条请求的时间都变,整个前缀哈希全错位,命中率无限接近 0。

排查手段很简单:把请求日志里的前缀 token 抽样拉出来,找“前 N 个 token 是否完全一致”。不一致就看那一段软编码在哪,把动态内容挪到前缀后面,或者干脆在分块前对前缀段做归一化替换。这个问题在 Agent 场景里特别普遍,几乎每个接入的人都会踩一次。

5.3 问题二:量化压缩后工具调用变蠢

一开始为了追求显存省得更多,我把 KV Cache 全链路都开了 INT4。结果跑了一段时间,发现 Agent 在工具调用环节开始“犯傻”:明明工具 schema 给全了,却一直选错工具或漏参数。后来定位到是 KV 量化的精度损失在注意力层被放大,尤其是长距离依赖的块。

解决方案是开“混合精度保护名单”:系统提示词和工具 schema 对应的前缀块强制 FP16,只有后面的长上下文历史块才允许 INT8。这样显存占用比全 FP16 少了大概 30%,同时精度损失基本看不出来。如果你对 Agent 的稳定性有严格要求,我建议非热点区域也别低于 INT8。

5.4 问题三:磁盘换入换出导致请求毛刺

冷 KV 块放到 CPU 内存甚至磁盘,这一步虽然省显存,但会带来新的延迟风险。实测里,冷块从磁盘换回 GPU 显存,单次就要增加几百毫秒的额外延迟;如果大量请求同时触发换入,GPU 和 CPU 之间的拷贝带宽会被打满,整机请求都会出现明显毛刺。

这个问题的解法不在缓存侧,而在调度侧。引擎会预估“即将到达的请求需要哪些冷块”,提前把它们从磁盘搬到 CPU 内存,等请求真正到达时,只需要从 CPU 侧拷贝一份到 GPU,延迟基本平滑。这就要求调度引擎能读懂 Agent 任务的工作流,比如“工具结果返回之后大概率会继续读取某份文档”,这种预取能力是 KV Cache 调度从“能用”到“好用”的分水岭。

6. 一点经验之谈

这套 KV Cache 调度与加速引擎,我最深的感触是:它把“显存优化”这个问题从被动防守变成了主动出击。以前我做长上下文 Agent,满脑子想的都是“有没有更省显存的模型结构”“量化能不能再压一档”,总是跟显存上限较劲。但现在思路完全反过来了:既然 KV Cache 的访问模式有规律可循,那就把规律利用起来,让重复的内容只算一次,让热的内容留在原地,让冷的内容提前准备好。

跑了一圈下来,我个人的建议是:不要一上来就追求最激进的量化方案,先把块级复用、共享前缀树和亲和路由这些“调度层”的能力用好。这一步能给你带来的显存收益,往往比压精度更大,而且没有任何精度损失。等命中优化做到极致了,再去考虑 KV 量化和磁盘分层,效果才能叠加起来。

最后说个小技巧,调参的时候不要死盯显存占用这一个指标。KV Cache 调度做得好的系统,显存占用和控制前可能差不多,但吞吐量和延迟会有明显差异,有高并发长上下文的 Agent 场景,这两项才是真正决定成本的关键。合理的目标,是让同样的显存扛住更多的并发。

相关新闻

学了3个月Agent还只会Demo?用这5项工程能力做一次自测

学了3个月Agent还只会Demo?用这5项工程能力做一次自测

学了3个月Agent还只会Demo?用这5项工程能力做一次自测 一个Agent Demo可以很精彩:输入目标,自动搜索,最后生成一份报告。但让另一个人使用时,换了问题就报错,重启进程任务消失,超时后不知道执行…

2026/10/20 2:13:24 阅读更多 →
2024上教资备考资料包:科一综合素养+科二教育知识,中学小学双版本覆盖

2024上教资备考资料包:科一综合素养+科二教育知识,中学小学双版本覆盖

资料概述 这是一套面向2024年上半年中小学教师资格证考试笔试的备考资料,涵盖科目一"综合素质"和科目二"教育知识与能力"两部分内容。资料以Polaris整理的个人学习笔记为基础,分为中小学通用版本,其中科二针对中学和小学…

2026/10/20 2:13:24 阅读更多 →
Day90-Java后端工程师的AI时代竞争力地图

Day90-Java后端工程师的AI时代竞争力地图

这套专栏走到今天:正篇 90 篇打底,续集《AI 工程化深水区》60 篇接着往生产级走,加起来 150 篇、22 个阶段。你现在的位置和要去的地方,都在这张图里:上半部分是正篇——前 8 个阶段(Day 1-56)把…

2026/10/20 2:12:24 阅读更多 →

最新新闻

从URL取参到Cookie操作:前端开发完整指南与踩坑记录

从URL取参到Cookie操作:前端开发完整指南与踩坑记录

老读者可能还记得,我之前在某公司的运营后台系统里做过一次页面重构,其中有个特别不起眼但又绕不开的需求:从前端拿 URL 上携带的参数,顺手把一些状态写进 Cookie。听起来简单,真正动手的时候才发现,这里面…

2026/10/20 2:54:46 阅读更多 →
不复杂的复杂度:Java开发者必备的大O分析指南

不复杂的复杂度:Java开发者必备的大O分析指南

第八篇了。前面我们用了几篇的篇幅,把Java的语法、面向对象、集合框架、I/O、异常这些基础内容过了一遍。今天想插一个看起来不太一样、但实际非常重要的主题——复杂度分析。为什么在这个节点讲它?因为我发现很多人在前面那些内容学完之后,开…

2026/10/20 2:54:46 阅读更多 →
需求分级与优先级管理:产研团队高效协作的落地指南

需求分级与优先级管理:产研团队高效协作的落地指南

周五下午三点,我正在跟团队过下一迭代的排期。会议室的门被推开,某业务线负责人带着一份PPT走进来,说有一位大客户急需一个定制功能,客户已经在催,下周要看到演示,否则可能影响续约。会议室安静了几秒&…

2026/10/20 2:54:46 阅读更多 →
降AI率工具实测:九类工具原理、风险与一套可复用工作流

降AI率工具实测:九类工具原理、风险与一套可复用工作流

开头部分可以这么写:最近不少本科生来找我看论文初稿,十份里有八份开头都是“随着社会的不断发展”,第二段必是“综上所述”。一问才知道,都是让AI先写一版,自己再改,改完一检测,“AI率”飙到百…

2026/10/20 2:54:46 阅读更多 →
Llama 2 提示词完全指南:模板、参数与实战技巧

Llama 2 提示词完全指南:模板、参数与实战技巧

最近几周我一直在折腾基于 Llama 2 的几个实际项目,从本地部署到 API 接入都走了一遍。反复试下来发现一个很多人容易忽略的事实:Llama 2 和 GPT 系列这类闭源模型的对话习惯差异非常大,直接把原来惯用的提示词搬过去,效果会肉眼可…

2026/10/20 2:54:46 阅读更多 →
大模型Skills应用实战:在Trae中把提示词变成可复用工作流

大模型Skills应用实战:在Trae中把提示词变成可复用工作流

这个系列写到第14篇,我聊点真正能提效的东西——大模型Skills应用。之前几篇要么在讲模型能力边界,要么在讲上下文工程,这次把视角落到一个具体场景:在Trae这款AI原生IDE里,怎么把Skill从"听说过"变成"…

2026/10/20 2:53:45 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

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

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

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

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

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

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 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/19 2:54:50 阅读更多 →
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/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练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/18 12:16:16 阅读更多 →