image-rs 的 fast_blur 加速 5.9 倍:整數累積器與倒數乘法
apas.tel · 2026-05-16
image-rs 的 fast_blur 函式實作了以三次連續 box blur 近似 Gaussian blur 的演算法(sigma 無關的 O(1) 複雜度)。2026 年 5 月的優化在不改變輸出品質的情況下,將執行時間從 51ms 壓縮至約 9ms(σ=7,1920×1080 RGBA),相當於影片處理從 19 FPS 提升至 120 FPS。
原本的問題
原始實作的熱路徑將每個 u8 子像素轉換為 f32、進行浮點數累積,再透過 roundf 轉換回來。火焰圖分析顯示三個主要瓶頸:
roundf:27% 執行時間to_f32類型轉換:22% 執行時間min/max操作:20% 執行時間
優化一:u32 整數累積器
將浮點累積改為 u32 整數累積,以整數除法取代 roundf:
// 原始:浮點路徑
result = rounding_saturating_mul(sum as f32, inv_kernel);
// 新版:整數路徑
result = ((sum + kernel_size / 2) / kernel_size) as u8;u32 的上限足以安全累積 blur kernel 值(u32::MAX / 255 ≈ 1680 萬),無溢位風險。此優化帶來 ~1.83 倍加速,消除所有 roundf 與浮點轉換開銷。
優化二:倒數乘法取代除法
基於 Granlund & Montgomery(1994)研究,以預計算倒數取代每像素的整數除法。除法需要 20–30 個 CPU cycle 且阻塞 pipeline;乘法加位移只需 3–4 個 cycle:
struct U8Weight {
reciprocal: u32, // ceil(2^32 / kernel_size)
rounding_bias: u32, // kernel_size / 2
}
// 除法替換:
((sum as u64 * reciprocal as u64) >> 32) as u8此步驟帶來 ~3.2 倍的額外加速。
基準測試結果
| Sigma | 優化前 | 優化後 | 加速 |
|---|---|---|---|
| σ=3 | 51.1 ms | 8.6 ms | 5.9× |
| σ=7 | 51.5 ms | 9.0 ms | 5.7× |
| σ=50 | 52.2 ms | 10.2 ms | 5.1× |
最終實作透過 BlurAccumulator trait 支援多像素類型:u8 使用 u32 快速路徑,其他類型(u16、f32、f64)退回 f32 累積器,在不引入執行時分支的情況下維持泛型設計。
原始來源:apas.tel
Bun 的 Rust 移植:6,755 個 AI 生成的 commit 帶來的工程疑慮
Jia-Cai Liu Blog · 2026-05-16
Bun JavaScript runtime 完成了從 Zig 到 Rust 的全面移植,6,755 個 commit 在六天內合入主幹,代碼幾乎全由 Claude 生成並由 Claude 審查。作者 Liu Jia-Cai 分析這次移植的技術背景,以及以 AI 生成代碼為主要生產基礎帶來的長期隱患。
移植的動機
Bun 原始的 Zig 代碼庫累積了 use-after-free、double-free 與錯誤路徑記憶體洩漏等問題。Liu 認為這反映的是語言與團隊文化之間的結構性不匹配:Bun 的快速迭代文化與 Zig 要求精細手動記憶體管理之間存在根本張力。Rust 編譯器的靜態保證讓團隊在快速迭代時免於記憶體安全問題,這是移植的核心邏輯。
技術隱患
Liu 指出 AI 代碼翻譯可以在局部達到語意等價,但無法保證跨函式的全域不變量(global invariants)——那些沒有寫進測試、卻隱含在設計意圖中的系統約束。測試套件驗證的是已知行為在已知路徑上的正確性,對錯誤處理邊界條件與全域系統不變量的覆蓋存在固有局限。
六天內合入、無人工完整審查的 6,755 個 commit,意味著這個代碼庫的可調試性(debuggability)存疑:未來發生線上事件時,工程師需要理解並修改一個從未被人類深度閱讀的代碼庫。
預測
Liu 預測短期穩定性因測試覆蓋率與金絲雀部署而得以維持,但長期的結構性風險在於:AI 生成的生產代碼在技術上合規,卻缺乏人類理解這個基礎,使工程組織在未來複雜調試情境下面臨不確定性。
原始來源:Jia-Cai Liu Blog
OxCaml 的資料競爭自由:以模式系統在編譯期阻斷競爭條件
KC Sivaramakrishnan Blog · 2026-05-07
OxCaml 是 Jane Street 基於 OCaml 5 的擴展方言,透過在型別系統中引入模式(modes)的正交標注,在編譯期靜態保證多 domain 程式不存在資料競爭。作者 KC Sivaramakrishnan 詳細說明其類型系統設計,以及與 OCaml 5 原生 domain 模型的整合方式。
模式系統的兩個維度
OxCaml 新增兩個正交的模式軸:
- Contention 軸(
uncontended ⊑ shared ⊑ contended,預設uncontended):追蹤值是否可能被多個 domain 同時存取。讀取或寫入可變欄位需要uncontended狀態;contended值的可變欄位操作被禁止,因為「另一個 domain 可能正在寫入」。 - Portability 軸(
portable ⊑ nonportable,預設nonportable):決定值是否可安全跨 domain 邊界傳遞。送至其他 domain 的 closure 必須是portable;其中的捕獲值自動變為contended。
競爭自由的保證機制
資料競爭的四個必要條件(多個 domain、共享狀態、並發寫入、普通 ref)在 OxCaml 的型別系統中無法同時滿足:portable closure 中的可變欄位因 contention 規則而不可存取,編譯器在任何代碼執行前即拒絕有問題的模式。
需要共享可變狀態時,Portable.Atomic.t 類型同時具備 portable 與 uncontended 屬性,允許透過原子操作安全地跨 domain 讀寫計數器等共享資料,而無需手動加鎖。
與 OCaml 5 的關係
OCaml 5 原生允許未同步的 closure 共享跨 Domain 邊界,開發者需自行避免競爭;OxCaml 的類型檢查器將這個責任從執行期移至編譯期,在未同步的共享被允許之前就予以拒絕。