[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f9WUJcQrk1bXm4y3mbFdarqaxWmz5AIm1VNpUbW72wJQ":3},{"item":4,"related":48},{"id":5,"type":6,"title":7,"slug":8,"summary":9,"body":10,"coverUrl":11,"productScreenshots":12,"productLinks":13,"authorName":14,"authorUrl":15,"authorSubject":16,"category":17,"tags":22,"sourceLabel":39,"sourceName":40,"sourceUrl":41,"status":42,"seoTitle":7,"seoDescription":9,"canonicalUrl":39,"isFeatured":43,"sno":44,"sortOrder":45,"publishedAt":46,"updatedAt":47,"createdAt":47},"fe8fa404-64b1-4af5-8e18-a2d25284b93c","article","Superoptimization：普通编译器做不到的极致优化，怎么搜出来？","superoptimization-machine-code-search-explained","Superoptimization 把一小段程序当成谜题，搜索更短或更快的机器级实现，再用约束求解器验证候选方案是否等价。本文解释它和普通编译器优化的区别，以及为什么 AI 生成的短代码不等于高性能代码。","编译器优化通常有明确规则：消除无用代码、合并常量、把循环展开，或者把函数调用内联。但机器指令的组合空间非常大，规则写得再多，也不可能穷举所有短小而正确的实现。Superoptimization，中文常译作“超优化”，就是把一个小程序当成谜题，直接搜索更短或更快的机器级实现。\n\n## 它和普通优化有什么不同\n\n普通编译器通常在速度和编译时间之间取平衡。它希望在几秒或几分钟内，把很大的程序优化到“足够好”。超优化器则可以为一段很小的热代码花更长时间，枚举指令序列、建立约束，再验证候选实现是否与原程序等价。\n\n以一段 LLVM IR 为例，工具可能先观察输入输出关系，再尝试生成不同的指令组合。候选方案不能只看文本长度，还要考虑寄存器、分支、目标 CPU 的指令集，以及未定义行为和溢出语义。一个看起来更短的方案，如果在边界输入上算错，就不能称为优化。\n\n## 为什么搜索不会立刻爆炸\n\n真正的超优化不会把所有机器指令无限排列。它会限制序列长度、操作数范围和可用指令集，并利用 SMT 求解器检查“是否存在某个输入让新旧程序结果不同”。如果找不到反例，候选就更有机会被接受；如果找到了反例，搜索会继续排除这一类方案。\n\n这说明超优化的核心不是蛮力，而是搜索、约束和证明的组合。搜索负责提出新想法，约束求解器负责过滤，成本模型负责排序，最终还要在真实目标上测试。\n\n## 它什么时候有价值\n\n密码学原语、编解码内核、数据库热点循环、数学库函数和嵌入式代码，都可能值得做局部超优化。普通业务代码通常不适合，因为编译时间、验证成本和维护成本会很快超过收益。\n\n对 AI 编程来说，超优化提供了一个重要提醒：AI 生成的“更短代码”不等于更高性能。真正的优化必须说明目标机器、输入边界、正确性证据和基准结果。把代码改漂亮只是重写，把可验证的等价实现改得更快，才接近超优化。\n\n## 读者应该记住\n\nSuperoptimization 的问题可以概括为：“有没有一段更小的程序，能在所有允许输入上得到同样结果？”它把优化从经验规则推向程序搜索与形式化验证，但最适合小而关键的代码片段。\n\n资料：[Souper Superoptimizer](https:\u002F\u002Fgithub.com\u002Fgoogle\u002Fsouper)；[Souper 论文](https:\u002F\u002Farxiv.org\u002Fabs\u002F1711.04422)","\u002Fuploads\u002F2026-09-20\u002F3f79618a-e0f3-4a24-a468-c2ec89ac6888.jpg",[],[],"Foundit","https:\u002F\u002Ffoundit.cn","foundit-ai-editorial",{"id":18,"name":19,"slug":20,"description":21},"6179d3b6-dc34-4483-9ded-3cd9f1b37a47","科普","abbreviation","介绍各领域新兴概念",[23,27,31,35],{"id":24,"name":25,"slug":26},"144abe77-0dc6-4f66-a176-20bddb1c0bfa","编程","coding",{"id":28,"name":29,"slug":30},"a202d639-99a6-488a-a712-4d4c6ffd7e15","开发","dev",{"id":32,"name":33,"slug":34},"7c76bfc2-f80f-4ee0-a95d-27bd8708b434","技术","slug",{"id":36,"name":37,"slug":38},"4c2bbea6-eab7-40a8-8447-1de478ff7749","分析","analyse",null,"Souper Superoptimizer","https:\u002F\u002Fgithub.com\u002Fgoogle\u002Fsouper","published",false,52,0,"2026-09-20T00:00:00.000Z","2026-09-20T03:57:43.436Z",[49,57,65],{"id":50,"type":6,"title":51,"slug":52,"summary":53,"coverUrl":54,"authorName":14,"sno":55,"publishedAt":46,"createdAt":56},"d0700249-defa-43a1-a66a-4455c6889072","ABI：为什么源码能编译，二进制却不能互相调用？","application-binary-interface-abi-explained","ABI 是二进制世界的调用合同，规定参数传递、对象布局、符号命名和异常处理。本文区分 ABI 与 API，解释动态库、C++ 兼容性和跨语言绑定为什么不能只看函数签名。","\u002Fuploads\u002F2026-09-20\u002F33666a48-4e8f-42a3-9ffd-f4c490498689.jpg",42,"2026-09-20T03:58:01.058Z",{"id":58,"type":6,"title":59,"slug":60,"summary":61,"coverUrl":62,"authorName":14,"sno":63,"publishedAt":46,"createdAt":64},"c9f4e936-9533-4b9c-a1de-f03ef09fed37","WAL：为什么数据库要先写日志，再写真正数据？","write-ahead-logging-wal-database-explained","WAL 要求描述数据变化的日志先于数据页持久化，让数据库可以延迟刷写并在崩溃后通过重放恢复。本文用账本和收据解释 REDO、检查点、复制与持久性设置的关系。","\u002Fuploads\u002F2026-09-20\u002F6260c953-345b-4c9d-b3d6-6202c7e5539c.jpg",43,"2026-09-20T03:58:15.082Z",{"id":66,"type":6,"title":67,"slug":68,"summary":69,"coverUrl":70,"authorName":14,"sno":71,"publishedAt":46,"createdAt":72},"41d50774-50df-4e2f-b1b3-ab6d9f329726","Backpressure：生产者太快时，系统怎样不被数据淹没？","backpressure-reactive-streams-explained","Backpressure 让下游处理能力反过来影响上游生产速度，避免异步流水线靠无限缓存硬撑。本文用水管和阀门解释响应式流、需求信号、数据丢弃与容量设计，也说明它和普通限流的区别。","\u002Fuploads\u002F2026-09-20\u002F35c47792-3d4b-46ae-9375-c68e4c53330e.jpg",45,"2026-09-20T03:58:08.835Z"]