如果我有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
Run Code Online (Sandbox Code Playgroud)
快速记下来(因此未经测试):
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);
}
Run Code Online (Sandbox Code Playgroud)
对于最小/最大,替换_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);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3020 次 |
| 最近记录: |