You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用SIMD检查__m128i中奇偶通道是否在指定范围内?

高效检查__m128i向量中奇偶索引字节的范围合法性

我们有一个存储16个无符号char的__m128i向量,其中**偶数索引(0、2、4……14)**的字节需落在[even_min, even_max]区间,**奇数索引(1、3、5……15)**的字节需落在[odd_min, odd_max]区间。示例如下:

// 合法示例
vec1: [1, 5, 6, 10, 2, 6, 4, 6, 2, 7, 4, 9, 2, 7, 4, 8] 

// 非法示例:第0位(偶数索引)超过even_max
vec2: [8, 5, 6, 10, 2, 6, 4, 6, 2, 7, 4, 9, 2, 7, 4, 8]

现有实现方案

你当前采用分两组检查的方式,逻辑直观但存在优化空间:

// 用于无符号char的包含性比较宏
#define _mm_cmpge_epi8(a, b) _mm_cmpeq_epi8(_mm_max_epu8(a, b), a)
#define _mm_cmple_epi8(a, b) _mm_cmpge_epi8(b, a)

// 检查偶数索引字节
__m128i even_min = _mm_set1_epi8(xxx);
__m128i even_max = _mm_set1_epi8(xxx);
__m128i even_mask = _mm_set_epi8(0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1);

__m128i evenRange = _mm_and_si128(_mm_cmpge_epi8(vec, even_min), _mm_cmple_epi8(vec, even_max));
bool isEvenOk = _mm_testc_si128(evenRange, even_mask);

// 奇数索引字节的检查逻辑与上述类似

更高效的优化方案

通过合并奇偶范围的比较逻辑,可以减少SIMD指令调用次数,提升执行效率:

  1. 构造混合min/max向量:将even_min放在偶数索引位,odd_min放在奇数索引位;同理构造max向量。
  2. 一次性完成所有字节的范围检查,再用掩码分别验证奇偶位的合法性。

优化后的代码示例:

#define _mm_cmpge_epi8(a, b) _mm_cmpeq_epi8(_mm_max_epu8(a, b), a)
#define _mm_cmple_epi8(a, b) _mm_cmpge_epi8(b, a)

// 构造奇偶混合的min向量:偶数位为even_min,奇数位为odd_min
__m128i min_vec = _mm_setr_epi8(
    even_min_val, odd_min_val, even_min_val, odd_min_val,
    even_min_val, odd_min_val, even_min_val, odd_min_val,
    even_min_val, odd_min_val, even_min_val, odd_min_val,
    even_min_val, odd_min_val, even_min_val, odd_min_val
);

// 构造奇偶混合的max向量:偶数位为even_max,奇数位为odd_max
__m128i max_vec = _mm_setr_epi8(
    even_max_val, odd_max_val, even_max_val, odd_max_val,
    even_max_val, odd_max_val, even_max_val, odd_max_val,
    even_max_val, odd_max_val, even_max_val, odd_max_val,
    even_max_val, odd_max_val, even_max_val, odd_max_val
);

// 一次性完成所有字节的范围检查:合法字节为0xFF,非法为0
__m128i all_valid = _mm_and_si128(_mm_cmpge_epi8(vec, min_vec), _mm_cmple_epi8(vec, max_vec));

// 奇偶索引掩码
__m128i even_mask = _mm_set_epi8(0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1);
__m128i odd_mask = _mm_set_epi8(-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0);

// 验证奇偶位是否全部合法
bool isEvenOk = _mm_testc_si128(all_valid, even_mask);
bool isOddOk = _mm_testc_si128(all_valid, odd_mask);
bool isAllOk = isEvenOk && isOddOk;

额外优化技巧(AVX2环境)

如果你的编译环境支持AVX2指令集,可以用_mm_shuffle_epi8快速构造混合min/max向量,尤其适合min/max为变量的场景:

__m128i even_min_vec = _mm_set1_epi8(even_min_val);
__m128i odd_min_vec = _mm_set1_epi8(odd_min_val);
// 交叉排列even和odd的min值
__m128i shuffle_mask = _mm_setr_epi8(0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16, 0, 16);
__m128i min_vec = _mm_shuffle_epi8(_mm_unpacklo_epi8(even_min_vec, odd_min_vec), shuffle_mask);

内容的提问来源于stack exchange,提问作者chenzhongpu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 19:04:57