[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f8VE8QJF2nDtLpy_N7G2rRoi759mw47UF_XPgmMndXCc":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},"55f81c45-2885-485f-94b4-333c3f850f09","article","E-graphs：AI 如何同时保留一百种等价写法，最后挑出最好的？","e-graphs-equality-saturation-explained","E-graph 把许多语义等价的表达式放在同一张图里，等候选方案足够丰富后，再依据速度、体积或能耗统一选择。本文用地铁换乘图解释 equality saturation，说明它为什么适合编译器、查询优化，也能启发 AI 编程先保留方案再做决策。","很多程序优化看起来像是在“改写代码”：把一个表达式换成更短的表达式，把一串计算折叠成一个常量。但如果每改一步就丢掉旧方案，编译器很容易走进局部最优。E-graph 提供了另一种思路：先把等价的写法放在一起保存，等候选方案足够丰富后，再统一挑出成本最低的一种。\n\n## 它解决的是什么问题\n\n假设 `a * 2` 可以写成 `a + a`，而 `a + a` 又可以在某些硬件上变成一条更快的指令。传统重写会沿着一条路径不断替换，替换方向和顺序都会影响最终结果。E-graph 则把这些表达式放进同一个等价类，表示“它们在语义上可以互相替代”，但暂时不急着删除任何一个。\n\n这也是 equality saturation 的关键：不断应用安全的重写规则，让等价类“长大”，直到没有值得继续加入的等价表达式；然后再用一个成本模型做 extraction，选择指令数量、延迟、能耗或寄存器压力更低的版本。\n\n## 可以把它想成什么\n\n把 E-graph 想成一张不断扩张的地铁换乘图。不同路线可能经过不同站点，但它们都能把乘客送到同一个目的地。普通优化像是走到一个换乘站就删掉其他路线；e-graph 则保留多条路线，最后根据时间、票价或换乘次数选最合适的一条。\n\n它并不等于“任何改写都安全”。重写规则必须维护等价关系，成本模型也必须符合目标平台。一个在桌面 CPU 上更短的表达式，可能在 GPU、向量指令或特定缓存层次上并不更快。\n\n## 为什么和 AI 编程有关\n\nAI 编程经常会给出多种可行实现：递归、循环、批处理、缓存，甚至不同的数据结构。E-graph 提供了一个很有启发性的工程思路：不要让第一次生成的方案成为唯一方案，而是把可证明等价的候选集中管理，再按可解释的成本选择。\n\n这类方法尤其适合查询优化、张量表达式、算术化简和编译器后端。它的代价是图可能快速膨胀，因此现实系统需要限制规则、控制节点数量，并把“更好”定义清楚。\n\n## 读者应该记住\n\nE-graph 的核心不是一棵更复杂的语法树，而是“同时保存许多等价程序”。Equality saturation 则把“边改边丢候选”改成“先积累可能性，最后统一决策”。当 AI 能快速产生方案时，这种先保留、后选择的思路也能帮助人类避免过早锁定答案。\n\n资料：[egg：Fast and Extensible Equality Saturation](https:\u002F\u002Fdoi.org\u002F10.1145\u002F3815481)","\u002Fuploads\u002F2026-09-20\u002Fe9999469-64b1-4d20-a4c9-b3ba1f10ac27.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},"88d2bc27-0e0f-468a-b907-2991cb97b87b","人工智能","ai",{"id":28,"name":29,"slug":30},"144abe77-0dc6-4f66-a176-20bddb1c0bfa","编程","coding",{"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,"egg：Fast and Extensible Equality Saturation","https:\u002F\u002Fdoi.org\u002F10.1145\u002F3815481","published",false,47,0,"2026-09-20T00:00:00.000Z","2026-09-20T03:57:41.871Z",[49,57,66],{"id":50,"type":6,"title":51,"slug":52,"summary":53,"coverUrl":54,"authorName":14,"sno":55,"publishedAt":46,"createdAt":56},"990d763f-115c-4589-9e7d-769d9050410e","SMT Solver：让机器回答“有没有满足这些条件的输入”","smt-solver-z3-constraints-explained","SMT Solver 专门处理带有整数、数组、位向量和逻辑条件的可满足性问题。本文以 Z3 为例，解释模型、反例和不可满足的含义，说明约束求解器如何帮助程序验证、测试生成和 AI 编程。","\u002Fuploads\u002F2026-09-20\u002F457baa75-2391-4085-8348-996f2420b162.jpg",58,"2026-09-20T03:57:47.026Z",{"id":58,"type":6,"title":59,"slug":60,"summary":61,"coverUrl":62,"authorName":14,"sno":63,"publishedAt":64,"createdAt":65},"5e0c84da-6011-41e8-b1f7-726c8bf0b30a","RCU：读多写少的系统，为什么敢让读者几乎不加锁？","rcu-read-copy-update-explained","RCU 把共享数据的更新与旧版本回收拆开，让读者以极低成本读取，同时等待所有旧读者离开后再释放内存。本文用导览图解释它的读侧、宽限期与适用边界。","\u002Fuploads\u002F2026-09-26\u002F3398ce37-ca4f-4cc3-84b3-fe931d2f055d.jpg",41,"2026-09-27T00:00:00.000Z","2026-09-26T16:25:40.784Z",{"id":67,"type":6,"title":68,"slug":69,"summary":70,"coverUrl":71,"authorName":14,"sno":72,"publishedAt":73,"createdAt":74},"0bc79f1c-f305-4d64-a9f8-589d1d6da0b3","EEVDF：Linux 如何判断哪个任务“最该先用 CPU”？","eevdf-linux-fair-cpu-scheduling","EEVDF 是 Linux 调度器的一种公平调度思路：先判断任务是否获得了应有份额，再按虚拟截止时间安排运行机会。本文用共享厨房的比喻，解释它如何兼顾长期公平与短期响应，并澄清它并非硬实时保证。","\u002Fuploads\u002F2026-10-13\u002Fdc59d374-8c78-41ba-bdfe-a6f0e62ab246.jpg",43,"2026-10-13T00:00:00.000Z","2026-10-13T02:13:28.103Z"]