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生成的线性扫描函数快得多,而且通过精巧的位操作避免了分支预测失败,在吞吐量和延迟上都达到了令人印象深刻的结果。