如何用SIMD检查__m128i中偶数lane匹配值时奇数lane的范围合规性
用SIMD Intrinsics检查16位char向量的奇偶lane约束
核心思路
我们需要将原向量的奇偶lane拆分,针对偶数lane的特定值批量检查对应奇数lane是否在指定范围,非特定值的偶数lane直接判定为合规。具体步骤如下:
- 拆分奇偶lane:通过字节洗牌指令提取所有偶数索引(0、2...14)和奇数索引(1、3...15)的元素到单独向量。
- 标记特定偶数lane:生成掩码标记哪些偶数lane等于目标值(如2、3)。
- 范围检查奇数lane:对标记的位置,批量验证对应奇数lane是否落在指定区间。
- 合并合规掩码:将非特定值的全合规掩码、特定值的合规掩码合并,最终判断所有位置是否都满足约束。
代码实现(SSE Intrinsics)
#include <emmintrin.h> #include <stdbool.h> bool check_simd_constraints(__m128i vec) { // 1. 拆分奇偶lane const __m128i even_mask = _mm_setr_epi8(0, -1, 2, -1, 4, -1, 6, -1, 8, -1, 10, -1, 12, -1, 14, -1); __m128i even_lanes = _mm_shuffle_epi8(vec, even_mask); const __m128i odd_mask = _mm_setr_epi8(-1, 1, -1, 3, -1, 5, -1, 7, -1, 9, -1, 11, -1, 13, -1, 15); __m128i odd_lanes = _mm_shuffle_epi8(vec, odd_mask); // 2. 生成特定值掩码:偶数lane等于2或3的位置标记为0xff,其余为0 const __m128i val2 = _mm_set1_epi8(2); __m128i mask_eq2 = _mm_cmpeq_epi8(even_lanes, val2); const __m128i val3 = _mm_set1_epi8(3); __m128i mask_eq3 = _mm_cmpeq_epi8(even_lanes, val3); // 3. 检查奇数lane的范围 // 偶数lane=2时,奇数lane需在[1,5] const __m128i range2_low = _mm_set1_epi8(1); const __m128i range2_high = _mm_set1_epi8(5); __m128i mask_range2 = _mm_and_si128(_mm_cmpge_epi8(odd_lanes, range2_low), _mm_cmple_epi8(odd_lanes, range2_high)); // 偶数lane=3时,奇数lane需在[4,6] const __m128i range3_low = _mm_set1_epi8(4); const __m128i range3_high = _mm_set1_epi8(6); __m128i mask_range3 = _mm_and_si128(_mm_cmpge_epi8(odd_lanes, range3_low), _mm_cmple_epi8(odd_lanes, range3_high)); // 4. 合并合规掩码:非特定值位置全合规,特定值位置取范围检查结果 __m128i non_spec_mask = _mm_andnot_si128(_mm_or_si128(mask_eq2, mask_eq3), _mm_set1_epi8(0xff)); __m128i mask_eq2_ok = _mm_and_si128(mask_eq2, mask_range2); __m128i mask_eq3_ok = _mm_and_si128(mask_eq3, mask_range3); __m128i all_ok = _mm_or_si128(_mm_or_si128(non_spec_mask, mask_eq2_ok), mask_eq3_ok); // 5. 检查所有位置是否都合规(全为0xff) return _mm_test_all_ones(all_ok) != 0; }
关键细节说明
- 洗牌指令:
_mm_shuffle_epi8通过预定义掩码一次性提取所有目标lane,效率远高于逐元素操作。 - 掩码运算:利用SIMD的按位与/或/非操作,批量处理8组约束判断,完全并行化。
- 编译期优化:所有常量(如特定值、范围、洗牌掩码)都可在编译期确定,编译器会生成更紧凑的机器码。
- 结果验证:
_mm_test_all_ones直接检查向量所有位是否为1,避免了手动提取每个元素判断的开销。
内容的提问来源于stack exchange,提问作者chenzhongpu
相关产品推荐
相关产品推荐

