基于AVX2的64位有符号整数逐元素最小/最大值计算优化问询
AVX2实现64位有符号整数逐元素最小/最大值的优化探讨
背景
在Intel 12/13代P核(Golden Cove/Raptor Cove)平台上,需要用AVX2指令集实现两组64位有符号整数数组的逐元素最小/最大值计算,但AVX2仅提供32位整数的最小/最大指令(VPMINSD/VPMAXSD),64位版本的VPMINSQ仅支持AVX-512,无法使用。
现有方案分析
初始方案:掩码+_mm256_blendv_epi8
通过VPCMPGTQ生成比较掩码,再用_mm256_blendv_epi8根据掩码混合两个向量。但_mm256_blendv_epi8在目标平台是3微操作指令,吞吐量受限场景下,处理一个256位向量(4个int64_t元素)需要约2.33周期,开销较大。
优化位运算方案:VPCMPGTQ+VPXOR+VPAND
利用位运算等价转换实现最小/最大值计算:
- 计算最小值:
min(a,b) = a ^ (mask & (a ^ b)),其中mask是a > b时为全1的64位掩码 - 对应指令序列:
__m256i mask = _mm256_cmpgt_epi64(a, b); __m256i xor_ab = _mm256_xor_si256(a, b); __m256i and_mask = _mm256_and_si256(mask, xor_ab); __m256i min_val = _mm256_xor_si256(a, and_mask);
该方案仅需4个微操作,在目标平台的吞吐量可达约1.66周期/向量,是目前单向量处理的最优方案。
更快实现方式探讨
要进一步提升吞吐量,循环展开是最有效的方向:
- 对循环进行2倍或4倍展开,同时处理多个256位向量,充分利用CPU的指令级并行(ILP)。例如展开2倍时,可并行执行两组
VPCMPGTQ、VPXOR等指令,将吞吐量提升至接近1周期/向量(每周期处理一个256位向量)。 - 目前没有单向量处理的指令组合能超越上述位运算方案的吞吐量——AVX2指令集中没有其他可直接替代的低开销指令,任何额外的指令拆分或转换都会增加微操作数,反而降低效率。
拆分-交换-拼接方案的合理性分析
针对数组高32位无冲突(即任意两个64位元素的高32位比较结果与整个64位比较结果一致)的特性,拆分-交换-拼接方案的思路是:提取高32位用VPMINSD/VPMAXSD计算,再混合低32位后拼接成64位结果。但该方案存在以下问题:
- 指令数远多于位运算方案,需要额外的洗牌(
VPSHUFD)、移位(VPSLLQ)等操作,单向量吞吐量约1.83周期,反而低于位运算方案。 - 即使高32位无冲突,该方案的延迟也没有优势——位运算方案的总延迟为4周期,而拆分方案的延迟因额外指令会更长。
因此,该方案仅在极端特殊的延迟场景(如某条指令端口被占用)可能有价值,在常规吞吐量受限或延迟受限场景下,合理性不高,不如直接使用位运算方案。
内容的提问来源于stack exchange,提问作者swineone
相关产品推荐
相关产品推荐

