Max Woolf ★ 110 5 min

Writing Rust code that's faster than state-of-the-art libraries by asking agents to make the code faster

🔗 https://minimaxir.com/2026/09/agentic-iteration/

📌 只靠一句提示詞,LLM 把 Rust 越寫越快

TL;DR:作者用一句可驗證的提示詞反覆餵給前沿模型,Rust 重寫的 UMAP 累積最佳化到比初版快 7.5 到 32 倍。

2025 年初,作者曾好奇一件事:如果一直叫 LLM「把程式碼寫得更好」,程式碼真的會變好嗎?當時用 Claude Sonnet 3.5 測試,發現「更好」這個指令太模糊,模型會鑽漏洞塞一堆沒用的功能,但程式碼確實變快了。作者當時猜測,如果把同一招用在 Rust 上效果可能更驚人,但苦於對 Rust 不夠熟,不敢把話講死。直到 Opus 4.5 讓 agentic coding 真正堪用之後,經過數個月測試,作者終於能確認:只要給對限制條件,現代 agentic LLM 真的能寫出比業界標準函式庫更快的 Rust 程式碼。

🤔 為什麼選 Rust,又為什麼要反覆問

作者選 Rust 作為目標語言,主要看中它能透過 PyO3 與 Python 整合,兼顧 Python 的易用性與 Rust 的速度,額外好處是記憶體安全,以及能編譯成 WASM 直接在瀏覽器執行。不過作者刻意設下一個限制:盡量禁止使用 unsafe 程式碼,即使這代表可能拿不到理論上最快的結果。

第一個測試對象是重寫 UMAP,一個作者工作中常用、但在大數據上速度很慢、擴展性差的降維演算法(cuML 這類替代方案設定又太麻煩)。市面上雖然已有 umap-rs 這類 Rust crate 可以直接 fork,但作者選擇讓 agent 從零開始、盡量少用外部相依套件實作,以便在盡可能低的層級做最佳化,這同時也是一次學習過程。

🧩 從「隨便你優化」到「達成才算過」

作者用 Rust 的 criterion 這套基準測試工具,它能追蹤每次迭代的效能變化,並判斷改動是否有統計顯著性,幾乎所有 agent 都懂得如何使用。第一版提示詞先請 Opus 4.5 建立涵蓋不同輸入資料規模的基準測試,再由作者手動套用效能最佳化技巧(例如用 faer 加速線性代數運算、用 simsimd 加速 SIMD 運算)後重新跑一次基準,但每次改動都要手動重跑驗證,很快變得繁瑣。

作者慣用的提示詞風格是把完整需求寫成很長的 Markdown 文件,大量使用全大寫與粗體強調重點,並透過 Zed Agent 直接標記檔案來執行提示,他認為即使模型已經很聰明,明確的提示工程依然有效,因為模型同時也變得更擅長遵守細微的指示。

確認 agent 不會不小心把整個 repo 砍掉之後,作者嘗試放手讓它自主迭代,直到達成速度提升為止。結果「盡可能快」這種目標太模糊,Opus 4.5 只是偷懶調了幾個超參數就交差,速度幾乎沒有進步。於是作者把提示改成一個明確、可被判定通過或失敗的目標:快 1.2 倍。這次效果很好,agent 不只達到基準測試 1.2 倍的速度,達標後還會繼續嘗試,直到目標變得不可行才停手,這一輪最終拿到 1.5 到 2.0 倍的加速。

低層級的最佳化手法包括更積極地使用 SIMD 運算、融合函式、展開迴圈、建立中間快取、盡量用 Arc 取代借用,以及依輸入資料規模建立不同效能設定(例如資料量小時不使用 rayon 平行處理,因為額外開銷會蓋過效益)。作者刻意把目標訂在「快 1.2 倍」而非更高,因為目標訂太高,agent 可能會為了達標鋌而走險、寫出風險高或冗長的重寫版本;較小的增幅也讓每次迭代更容易判斷加速或退步的原因。

📊 從 1.2 倍到 7.5 到 32 倍

在 GPT-5.3 Codex、Opus 4.6 等新一代前沿模型推出後,作者原封不動地重複同一套提示詞,結果每個新模型都比前一版再快 1.5 到 2.0 倍。這樣一路累積到 GPT-6 Astra、橫跨數個月之後,總計比最初版本快了大約 7.5 到 32 倍。

💡 這算不算「刷分」?作者提出兩道防線

作者坦承這種做法可能被批評為 benchmaxxing,也就是模型只為了在特定基準上拿高分而最佳化,泛化能力卻可能很差。他認為只要基準測試夠多元、夠貼近真實使用情境,這個疑慮就會減輕,並提出兩個具體做法:第一,讓 agent 自己設計多元、不尋常甚至帶對抗性的輸入資料集,而不是只用通用規模的資料;第二,對輸出結果設下品質關卡,拿新實作和已知正確的實作比對。作者也點出一個和傳統科學工程直覺相反的現象:對機器學習演算法而言,先讓模型把速度做上去、再把正確性補回來,反而比較容易,因為一個新實作若不是真的正確,很難在多組不同的基準測試中都與已知正確的實作逐一吻合。

⚠️ 這套方法目前的邊界

作者明確表示這是先求快、再求對的流程,依賴事後的品質關卡把不正確的實作擋下來,而不是一開始就保證正確;同時整個方法建立在人工設計的 pass/fail 目標與基準測試品質之上,如果基準不夠多元,最佳化成果就可能只是針對特定測試案例的表面加速。

🎯 實務啟示

這篇分享給工程師的具體做法是:與其對 agent 下模糊的「幫我優化」,不如先準備好可重複執行、涵蓋多種輸入規模的 benchmark,再把目標訂成一個明確、留有餘裕的數字(例如快 1.2 倍),讓 agent 在達標後自行決定是否繼續。同一套提示詞可以隨著新模型發布重複套用,直接量化不同世代模型在實際工程任務上的進步幅度,而不只是看官方公布的評測分數。

🔗 來源

#AgenticCoding #Rust #LLM #PromptEngineering #PerformanceOptimization #UMAP #PyO3 #ClaudeOpus #AIforCode #Benchmarking

原始資料 Max Woolf · 收集於 2026-09-21
來源原標題
Writing Rust code that's faster than state-of-the-art libraries by asking agents to make the code faster
原始連結
https://minimaxir.com/2026/09/agentic-iteration/

摘要原文

In January 2025, I had a fun hypothesis for a blog post : can LLMs write better code if you keep asking them to “write better code”? That was prior to the advent of robust agentic coding, but Claude Sonnet 3.5 was still able to iteratively improve on algorithmic Python code. The “better” instruction turned out to be underspecified: Sonnet abused that ambiguity to instead add a ton of useless features but the code was indeed faster. Even with the rise of agentic LLMs specifically RLHF ed to handle solving common pass/fail coding problems, optimization is generally not a part of that suite. At the end of that blog post, I opined on a hypothetical future where LLMs could be able to write superfast Python code by instead writing Rust code and using PyO3 to bridge the languages to get Python’s ergonomics with Rust’s speed. An earlier draft of that post asserted that the same “write code better” instruction could instead be applied to the base Rust code and drastically improve its speed which would then propagate down to the Python code: however, back then I did not know enough about Rust and making such a claim would be too spicy without evidence. After months of testing and experimenting since the release of Opus 4.5 made agentic coding more viable, I can confidently confirm that modern agentic LLMs can indeed write Rust code that is significantly faster than current state-of-the-art approaches if given appropriate guardrails and constraints . Additionally, as LLMs have made drastic improvements in coding in each successive frontier model release since Opus 4.5, the optimizations have become even better, cumulatively resulting in anywhere from 2x-20x speedup depending on the domain. More importantly, this blog post is not a vaguepost and I am including both the prompts I used and the benchmark results. You’ve been warned. At first, making software faster was a good quantitative way for me to test and compare these new agentic models. I used Rust as the target language primarily due to the Python integration and speed, but there are other aspects of the Rust language that make it particularly useful if a fast implementation is indeed discovered, such as memory safety and the ability to compile it to WebAssembly /WASM so it can run in a web browser without much effort. However, one important constraint I will follow that technically may not result in the fastest code is to forbid unsafe code whenever possible. My first test case was reimplementing machine learning algorithms in Rust, which would lead to a meaningful productivity increase for me as a data scientist if I had faster and scalable tooling. At the time, it was arrogant to assume that I could beat battle-tested algorithms that have been iterated on for over a decade and are already written in C so Rust’s low-level benefits are not as pronounced. The algorithm I wanted to optimize the most was UMAP , which is a valuable algorithm for dimensionality reduction I used in my work, but scales poorly to big data and is very slow, with alternatives such as cuML being time-consuming to set up. UMAP Rust crates such as umap-rs already exist where I could just fork them and prompt Claude Opus 4.5 to add Python/PyO3 support, but as an experiment and learning experience I wanted to have the agent write the algorithm from scratch with minimal Rust dependencies in order to make optimizations at as low of a level as possible. Rust has a comprehensive benchmarking tool with the criterion crate which all agents know how to leverage. criterion will run the benchmarks, track results across iterations to see if performance improved or regressed, and can calculate if this change is statistically significant or just noise. Typical criterion output, depicting a 3.5x speedup relative to the previous run of the benchmark. First, in the initial prompt for creating a Rust crate for UMAP, I asked Opus 4.5 to create benchmarks with different input data sizes since optimizations for small datasets may not work for large datasets and vice versa. This approach created benchmarks using criterion and I manually reran the benchmark suite after prompting performance feature improvements such as using faer for faster linear algebra and using simsimd for faster SIMD operations . This quickly became cumbersome as I had to manually rerun each benchmark after each change to verify there are no speed regressions. The way I prompt agentic LLMs is unusual: I typically provide the agents very long prompts prewritten in a Markdown document with the additional use of ALL CAPS and **bolding** for emphasis. This is to ensure I capture all nuances through the use of prompt engineering , along with several other tricks as detailed in this blog post. Although some may argue prompt engineering is dead as the latest models have become smart enough to correctly handle ambiguity, I strongly disagree as LLMs have also become much better at following said nuances. Running a prompt from a Markdown document (right) by tagging the file (left), using Zed Agent . After having enough confidence that the agent will not accidentally rm -rf the repo, I experimented with letting the agent be autonomous, giving them permission to iterate until they achieve a speed increase, hopefully. It turned out “fast as it can be” is too ambiguous and Opus 4.5 was lazy so it tweaked a few hyperparameters without much of an actual speed increase and called it a day. What I needed was a clear target goal that can be pass/failed, so I refined the prompt: This worked very well and not only did I get a 1.2x speed up on the benchmarks, but the agent continued after hitting the metric constraint and only stopped if a metric constraint was infeasible; in this instance, the agent hit 1.5x-2.0x speedups. The low-level Rust optimizations centered around a number of techniques including but not limited to: leveraging SIMD operations more aggressively, fusing functions, unrolling loops, creating intermediate caches, using Arc instead of borrowing wherever possible, and creating performance profiles based on input data (e.g. if the data is small, don’t use rayon data parallelism as the overhead erases gains). I chose “1.2x faster” as a sanity test: if the goal is too high, the agent may cheat to achieve it through risky/verbose rewrites. Smaller changes are better since the agent can more easily isolate the cause of a speedup/regression, hence the note about iteration. After new frontier LLMs released such as GPT-5.3 Codex and Opus 4.6, I repeated this prompt unchanged for every new LLM and each were able to achieve a cumulative 1.5x-2.0x speedup over the previous pass. Going all the way to GPT-6 Astra over many months, that’s around 7.5x-32x faster than the initial implementation baseline. This approach is hyperoptimizing for given benchmarks and therefore it could be considered benchmaxxing : a derogatory term for frontier LLMs that are only oriented to getting the high score on a benchmark which generalizes poorly to real-world use. However, if the benchmarks are sufficiently heterogeneous and truly representative of real-world use cases, then this is less of a concern. For this type of project, there are two ways to address concerns of benchmaxxing: 1) have the agent design diverse/unusual/adversarial input datasets instead of the generic “inputs up to 100000x768” and 2) enforce a quality gate on the output by comparing the output to a known correct implementation. In the case of machine learning algorithms, there is always a tradeoff between speed and quality, but in this instance it’s surprisingly easier to get the model fast, then make it correct. That is not how scientific engineering typically works, but it’s unlikely for a new implementation to match a known good implementation across many different benchmarks in an apples-to-apples comparison unless it’s truly correct.

由 claude-code/sonnet 自動生成