如果我有8个打包的32位浮点数(__m256),那么提取所有8个元素的水平和的最快方法是什么?同样,如何获得水平最大值和最小值?换句话说,以下C++函数的最佳实现是什么?
float sum(__m256 x);  ///< returns sum of all 8 elements
float max(__m256 x);  ///< returns the maximum of all 8 elements
float min(__m256 x);  ///< returns the minimum of all 8 elements
快速记下来(因此未经测试):
float sum(__m256 x) {
    __m128 hi = _mm256_extractf128_ps(x, 1);
    __m128 lo = _mm256_extractf128_ps(x, 0);
    lo = _mm_add_ps(hi, lo);
    hi = _mm_movehl_ps(hi, lo);
    lo = _mm_add_ps(hi, lo);
    hi = _mm_shuffle_ps(lo, lo, 1);
    lo = _mm_add_ss(hi, lo);
    return _mm_cvtss_f32(lo);
}
对于最小/最大,替换_mm_add_ps和_mm_add_ss与_mm_max_*或_mm_min_*.
请注意,这对于一些操作来说是很多工作; AVX并不是真正有效地进行水平操作.如果您可以批量处理多个向量,则可以使用更有效的解决方案.
虽然斯蒂芬·佳能的答案可能是找到水平最大值/最小值的理想选择,但我认为可以为水平和找到更好的解决方案。
float horizontal_add (__m256 a) {
    __m256 t1 = _mm256_hadd_ps(a,a);
    __m256 t2 = _mm256_hadd_ps(t1,t1);
    __m128 t3 = _mm256_extractf128_ps(t2,1);
    __m128 t4 = _mm_add_ss(_mm256_castps256_ps128(t2),t3);
    return _mm_cvtss_f32(t4);        
}
| 归档时间: | 
 | 
| 查看次数: | 3020 次 | 
| 最近记录: |