256位AVX矢量中32位浮点的水平和
Horizontal sum of 32-bit floats in 256-bit AVX vector
我有两个浮点数组,我想使用SSE和AVX以尽可能低的延迟计算点积。我知道浮点运算有一个256位的点积,但我读过SO,这比下面的技术慢:(https://stackoverflow.com/a/4121295/997112)。
我已经完成了大部分工作,向量temp_sums
包含所有的和,我只需要在最后对temp_sum
中包含的所有八个32位和求和。
#include "xmmintrin.h"
#include "immintrin.h"
int main(){
const int num_elements_in_array = 16;
__declspec(align(32)) float x[num_elements_in_array];
__declspec(align(32)) float y[num_elements_in_array];
x[0] = 2; x[1] = 2; x[2] = 2; x[3] = 2;
x[4] = 2; x[5] = 2; x[6] = 2; x[7] = 2;
x[8] = 2; x[9] = 2; x[10] = 2; x[11] = 2;
x[12] = 2; x[13] = 2; x[14] = 2; x[15] = 2;
y[0] = 3; y[1] = 3; y[2] = 3; y[3] = 3;
y[4] = 3; y[5] = 3; y[6] = 3; y[7] = 3;
y[8] = 3; y[9] = 3; y[10] = 3; y[11] = 3;
y[12] = 3; y[13] = 3; y[14] = 3; y[15] = 3;
__m256 a;
__m256 b;
__m256 temp_products;
__m256 temp_sum = _mm256_setzero_ps();
unsigned short j = 0;
const int sse_data_size = 32;
int num_values_to_process = sse_data_size/sizeof(float);
while(j < num_elements_in_array){
a = _mm256_load_ps(x+j);
b = _mm256_load_ps(y+j);
temp_products = _mm256_mul_ps(b, a);
temp_sum = _mm256_add_ps(temp_sum, temp_products);
j = j + num_values_to_process;
}
//Need to "process" temp_sum as a final value here
}
我担心我需要的256位内部函数在AVX1之前不可用。
我建议尽可能使用128位AVX指令。它将减少一次跨域混洗的延迟(在Intel Sandy/Ivy Bridge上为2个周期),并提高在128位执行单元(目前为AMD Bulldozer、Piledriver、Steamroller和Jaguar)上运行AVX指令的CPU的效率:
static inline float _mm256_reduce_add_ps(__m256 x) {
/* ( x3+x7, x2+x6, x1+x5, x0+x4 ) */
const __m128 x128 = _mm_add_ps(_mm256_extractf128_ps(x, 1), _mm256_castps256_ps128(x));
/* ( -, -, x1+x3+x5+x7, x0+x2+x4+x6 ) */
const __m128 x64 = _mm_add_ps(x128, _mm_movehl_ps(x128, x128));
/* ( -, -, -, x0+x1+x2+x3+x4+x5+x6+x7 ) */
const __m128 x32 = _mm_add_ss(x64, _mm_shuffle_ps(x64, x64, 0x55));
/* Conversion to float is a no-op on x86-64 */
return _mm_cvtss_f32(x32);
}
您可以使用AVX(即_mm256_hadd_ps
的正确256位版本)模拟完整的水平加法,如下所示:
#define _mm256_full_hadd_ps(v0, v1)
_mm256_hadd_ps(_mm256_permute2f128_ps(v0, v1, 0x20),
_mm256_permute2f128_ps(v0, v1, 0x31))
如果你只使用一个输入向量,那么你可以稍微简化一下。
相关文章:
- 将应用程序从32位移植到64位时出现问题
- 正在解码MSVC 32位版本的程序集(作业).没有手术做什么
- qmake:检测目标位宽(32 位或 64 位)
- 如何在 64 位 vb.net Windows 应用程序中引用 32 位 dll
- 浮点数为 32 位和 64 位二进制表示形式
- C++易失性:保证 32 位访问?
- C++将 16 位值转换为 32 位值
- 如何在 64 位平台上计算 32 位哈希C++?
- C++中的24位到32位转换
- 在机器字大小等于 32 位的计算机上int64_t如何工作?
- uint32_t如何保证 32 位?
- 将代码从 32 位迁移到 64 位时出现问题 Visual Studio 2010
- 如何将32位字符与内联assembelyc++中的32位字符进行比较
- 一个32位版本的应用程序,建立在CentOS 6 x64上,当在较新的Linux上启动时,在"dl_itera
- x86 32位对Cuda的支持
- 我把我的编译器从32位转换为64位,但我仍然不能使用超过2GB:(为什么
- 如何使用Canny到32位灰度
- 如何忽略32位整数中的特定位
- Clang++的InterlockedExchange的32位调用约定错误,但MSVC可以
- 在node-gip binding.gyp文件中,如何根据系统结构(32位、64位)包含不同的库文件