Intel AVX-512下int8向量乘法性能优化及epi8支持疑问
8位整数向量乘法的高效实现与指令设计疑问
用户问题与现有实现
我实现了用于int8矩阵乘法的8位整数乘法(uint8_t或int8_t因无扩展操作效果一致),但以下代码运行效率极低,寻求更高效实现方案;同时咨询:为何Intel未提供epi8原生乘法指令?
现有代码:
inline __m512i int8_mul(__m512i a, __m512i b) { // Convert vectors INT8 to INT16 __m512i a_lo = _mm512_cvtepi8_epi16(_mm512_castsi512_si256(a)); __m512i a_hi = _mm512_cvtepi8_epi16(_mm512_extracti64x4_epi64(a, 1)); __m512i b_lo = _mm512_cvtepi8_epi16(_mm512_castsi512_si256(b)); __m512i b_hi = _mm512_cvtepi8_epi16(_mm512_extracti64x4_epi64(b, 1)); // Multiply vectors in INT16 __m512i mul_lo = _mm512_mullo_epi16(a_lo, b_lo); __m512i mul_hi = _mm512_mullo_epi16(a_hi, b_hi); // Combine results __m512i result = _mm512_setzero_si512(); result = _mm512_inserti64x4(result, _mm512_cvtepi16_epi8(mul_lo), 0); result = _mm512_inserti64x4(result, _mm512_cvtepi16_epi8(mul_hi), 1); return result; }
高效实现方案
现有代码的主要开销来自重复的数据拆分/转换操作和冗余的结果合并步骤,以下是优化后的实现:
优化后的代码
inline __m512i int8_mul(__m512i a, __m512i b) { // 提前拆分512位向量为两个256位的epi8子向量,避免重复指令调用 __m256i a_lo_256 = _mm512_castsi512_si256(a); __m256i a_hi_256 = _mm512_extracti64x4_epi64(a, 1); __m256i b_lo_256 = _mm512_castsi512_si256(b); __m256i b_hi_256 = _mm512_extracti64x4_epi64(b, 1); // 将epi8扩展为epi16(int8用符号扩展,uint8可替换为_mm512_cvtepu8_epi16零扩展) __m512i a_lo = _mm512_cvtepi8_epi16(a_lo_256); __m512i a_hi = _mm512_cvtepi8_epi16(a_hi_256); __m512i b_lo = _mm512_cvtepi8_epi16(b_lo_256); __m512i b_hi = _mm512_cvtepi8_epi16(b_hi_256); // 对应元素相乘(保留低16位结果) __m512i mul_lo = _mm512_mullo_epi16(a_lo, b_lo); __m512i mul_hi = _mm512_mullo_epi16(a_hi, b_hi); // 转换回epi8并直接合并结果,减少零初始化步骤 __m256i res_lo = _mm512_cvtepi16_epi8(mul_lo); __m256i res_hi = _mm512_cvtepi16_epi8(mul_hi); return _mm512_inserti64x4(_mm512_castsi256_si512(res_lo), res_hi, 1); }
额外优化建议(针对矩阵乘法场景)
如果你的最终场景是int8矩阵乘法,优先使用Intel专门提供的点积指令,而非单独实现乘法:
- 对于有符号int8,使用
_mm512_dpwssd_epi32:一次指令完成8对int8元素的乘积累加,输出int32结果 - 对于无符号uint8,使用
_mm512_dpbusd_epi32:功能类似,针对无符号数优化
这些指令将乘法和累加合并在硬件层面完成,比单独做乘法再累加的效率提升数倍,完全覆盖矩阵乘法的核心需求。
为何Intel未提供epi8原生乘法指令
主要基于硬件成本、实际需求和指令集优先级的权衡:
- 硬件成本与收益不对等:512位epi8向量包含64个元素,若实现原生乘法,需要64个独立的8x8乘法器,会大幅增加CPU核心的面积和功耗。而实际场景中,epi8的核心用途是矩阵乘法,这类场景更需要乘积累加(点积)而非单独乘法,Intel的点积指令可以共享加法器,硬件效率更高。
- 现有指令可替代:通过epi16乘法配合类型转换,已经可以实现epi8乘法的效果,虽然有额外开销,但对于非热点场景完全够用。
- 指令集设计优先级:AVX-512的扩展优先针对AI、HPC等高性能场景,比如bfloat16支持、向量掩码操作、点积加速等,这些场景的收益远大于单独的epi8乘法指令。
内容的提问来源于stack exchange,提问作者kdh
相关产品推荐
相关产品推荐

