如何高效将含32个uint8_t的__m256i转为4个__m256浮点向量
AVX2高效实现__m256i(uint8)到4个__m256(float)的转换
核心优化实现
针对32个无符号8位整数的__m256i向量,我们可以通过AVX2的128位提取+64位块重排指令,高效拆分出4组8个uint8数据,再完成无符号扩展与浮点转换,比你设想的方案更紧凑:
#include <immintrin.h> void unpack_uint8_to_float(__m256i input_32u8, __m256* out_floats[4]) { // 拆分__m256i为两个128位向量 __m128i low_128 = _mm256_castsi256_si128(input_32u8); __m128i high_128 = _mm256_extracti128_si256(input_32u8, 1); // 重排128位向量的高低64位,得到4个含8个uint8的目标块(低64位有效) __m128i block0 = low_128; // 原向量第0-7个uint8 __m128i block1 = _mm_shuffle_epi32(low_128, 0x4E); // 原向量第8-15个uint8(交换low_128的高低64位) __m128i block2 = high_128; // 原向量第16-23个uint8 __m128i block3 = _mm_shuffle_epi32(high_128, 0x4E); // 原向量第24-31个uint8 // 无符号扩展uint8到int32,再转换为float out_floats[0] = _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(block0)); out_floats[1] = _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(block1)); out_floats[2] = _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(block2)); out_floats[3] = _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(block3)); }
结合像素平方差业务的额外优化
你提到的场景是计算RGB通道平方差求和,完全可以跳过浮点转换,用整数运算实现,效率更高:
- 符号扩展差值到int16:
_mm256_sub_epi8的结果是有符号int8,直接用_mm256_cvtepi8_epi16完成符号扩展:
__m128i low_diff = _mm256_castsi256_si128(diff_32i8); __m128i high_diff = _mm256_extracti128_si256(diff_32i8, 1); __m256i low_16 = _mm256_cvtepi8_epi16(low_diff); __m256i high_16 = _mm256_cvtepi8_epi16(high_diff);
- 计算平方:用
_mm256_mullo_epi16完成int16乘法,得到int32的平方值:
__m256i low_sq = _mm256_mullo_epi16(low_16, low_16); __m256i high_sq = _mm256_mullo_epi16(high_16, high_16);
- 通道平方求和:通过排列指令对齐同像素的RGB通道平方值,再累加:
// 排列掩码:将G、B通道的平方值映射到对应R通道的位置 const __m256i perm_g = _mm256_setr_epi32(1,4,7,10,13,16,19,22); const __m256i perm_b = _mm256_setr_epi32(2,5,8,11,14,17,20,23); __m256i low_g_sq = _mm256_permutevar8x32_epi32(low_sq, perm_g); __m256i low_b_sq = _mm256_permutevar8x32_epi32(low_sq, perm_b); __m256i low_pixel_sum = _mm256_add_epi32(_mm256_add_epi32(low_sq, low_g_sq), low_b_sq); // 对high_sq执行相同操作得到high_pixel_sum
内容的提问来源于stack exchange,提问作者Mandelmus100
相关产品推荐
相关产品推荐

