AI無法編寫的IPv4解析器
本文介紹了一種無需SIMD指令的快速IPv4地址解析演算法,透過SWAR和位操作技巧實現高吞吐量。作者詳細解釋瞭如何將IP字串載入到u64暫存器中,利用動態掩碼校驗範圍,並透過查詢表處理點分隔符。基準測試顯示,該演算法在i7-7700K上達到2.60 GB/s的吞吐量,在非SIMD實現中表現優異。
本文深入探討了一種高效的IPv4地址解析演算法,該演算法不依賴於SIMD指令,而是利用SWAR(SIMD Within A Register)技術和位操作技巧,在通用暫存器上實現並行處理。作者從Daniel Lemire的部落格文章獲得靈感,但認為不應過度依賴AI生成高效能程式碼,而是透過手工最佳化達到極致效率。
演算法首先將IPv4地址字串(長度7-15字元)載入到兩個64位暫存器中:head包含前8位元組,tail包含最後8位元組。對於長度為7的字串,透過條件調整避免越界讀取。核心解析函式parseTwoTriplets每次處理兩個八位組(共6個數字字元),透過減去ASCII偏移(0x30)得到數值,再乘以位置權重(100、10、1)並利用pext指令提取結果。校驗部分透過特殊的加法(+0x76)檢測非法字元,並透過動態掩碼處理跨位元組的邊界條件(如百位為2時十位不能超過5)。
對於點分隔符的處理,演算法先透過異或(XOR 0x2E)定位點號,然後利用乘法雜湊對映到32個槽位的查詢表,獲取對應的pdep掩碼和移位量,從而正確排列有效位元組。最終版本使用pext替代乘法雜湊進一步提升速度。
基準測試在i7-7700K上對150萬個隨機IP地址進行64次解析,平均延遲5.11納秒/IP,吞吐量2.60 GB/s。與Robert Graham的基準對比顯示,該演算法在非SIMD實現中排名第二,僅次於BMI2版本。作者強調,即使有最好的想法,仍需透過嚴格測試發現邊界情況(如255.255.255被錯誤接受),並反覆檢查彙編程式碼消除浪費。
演算法經歷了至少6輪迭代最佳化,每次都在Compiler Explorer中檢查彙編輸出,並使用llvm-mca分析瓶頸。最終版本不僅比AI生成的線性掃描函式快得多,而且透過精巧的位操作避免了分支預測失敗,在吞吐量和延遲上都達到了令人印象深刻的結果。