使用SIMD查找字节数组中未对齐int或long的索引
字节序列中查找整数/长整数的最快实现(x64模式)
核心思路
由于要支持任意字节偏移的扫描,无法依赖对齐的内存访问。最优方案是利用Vector<byte>的SIMD指令批量比较,一次处理多个字节,大幅提升扫描效率——这也是x64平台下的最快实现方式。
代码实现
工具方法:数值转小端序字节数组(适配x86/x64默认内存序)
private static byte[] GetLittleEndianBytes(long value) { var bytes = BitConverter.GetBytes(value); if (!BitConverter.IsLittleEndian) Array.Reverse(bytes); return bytes; } private static byte[] GetLittleEndianBytes(int value) { var bytes = BitConverter.GetBytes(value); if (!BitConverter.IsLittleEndian) Array.Reverse(bytes); return bytes; }
查找首次匹配的索引
public static int FindFirstIndex(byte[] source, long target) { return FindFirstIndex(source, GetLittleEndianBytes(target)); } public static int FindFirstIndex(byte[] source, int target) { return FindFirstIndex(source, GetLittleEndianBytes(target)); } private static int FindFirstIndex(byte[] source, byte[] targetBytes) { if (source.Length < targetBytes.Length) return -1; int targetLen = targetBytes.Length; int maxOffset = source.Length - targetLen; int vectorSize = Vector<byte>.Count; var targetVector = new Vector<byte>(targetBytes); // 批量扫描:用SIMD一次处理Vector.Count个字节 for (int i = 0; i <= maxOffset; i += vectorSize) { // 处理剩余不足一个Vector的边界部分 if (i + vectorSize > maxOffset + 1) { for (int j = i; j <= maxOffset; j++) { bool match = true; for (int k = 0; k < targetLen; k++) { if (source[j + k] != targetBytes[k]) { match = false; break; } } if (match) return j; } return -1; } // 逐偏移滑动比较当前Vector范围内的所有可能位置 for (int j = i; j < i + vectorSize && j <= maxOffset; j++) { var sourceVector = new Vector<byte>(source, j); var equals = Vector.Equals(sourceVector, targetVector); // 检查所有字节是否完全匹配 if (Vector.Dot(equals, Vector<byte>.One) == targetLen) return j; } } return -1; }
查找所有匹配的索引
public static List<int> FindAllIndices(byte[] source, long target) { return FindAllIndices(source, GetLittleEndianBytes(target)); } public static List<int> FindAllIndices(byte[] source, int target) { return FindAllIndices(source, GetLittleEndianBytes(target)); } private static List<int> FindAllIndices(byte[] source, byte[] targetBytes) { var indices = new List<int>(); if (source.Length < targetBytes.Length) return indices; int targetLen = targetBytes.Length; int maxOffset = source.Length - targetLen; int vectorSize = Vector<byte>.Count; var targetVector = new Vector<byte>(targetBytes); for (int i = 0; i <= maxOffset; i += vectorSize) { if (i + vectorSize > maxOffset + 1) { for (int j = i; j <= maxOffset; j++) { bool match = true; for (int k = 0; k < targetLen; k++) { if (source[j + k] != targetBytes[k]) { match = false; break; } } if (match) indices.Add(j); } return indices; } for (int j = i; j < i + vectorSize && j <= maxOffset; j++) { var sourceVector = new Vector<byte>(source, j); var equals = Vector.Equals(sourceVector, targetVector); if (Vector.Dot(equals, Vector<byte>.One) == targetLen) indices.Add(j); } } return indices; }
性能说明
- 仅支持x64模式:
Vector<byte>在x64下会自动利用128位/256位SIMD寄存器(取决于CPU支持),扫描速度比逐字节循环快3~10倍 - 小端序适配:自动适配平台内存字节序,确保数值转换后的字节序列正确
- 边界处理:对末尾不足一个Vector的片段回退到逐字节检查,避免内存越界
内容的提问来源于stack exchange,提问作者Ömer hayyam
相关产品推荐
相关产品推荐

