Lio*_*o78 7 c++ simd vectorization avx sse2
我需要为混合单/双精度浮点向量构建单精度浮点内积例程,利用256位SIMD寄存器的AVX指令集.
问题:一个输入向量是float(x),而另一个是double(yD).
因此,在计算真正的内积运算之前,我需要将输入的yD向量数据从double转换为float.
使用SSE2指令集,我能够实现一个非常快速的代码,做我需要的,并且速度性能非常接近于矢量x和y都是浮点数的情况:
void vector_operation(const size_t i)
{
__m128 X = _mm_load_ps(x + i);
__m128 Y = _mm_movelh_ps(_mm_cvtpd_ps(_mm_load_pd(yD + i + 0)), _mm_cvtpd_ps(_mm_load_pd(yD + i + 2)));
//inner-products accumulation
res = _mm_add_ps(res, _mm_mul_ps(X, Y));
}
Run Code Online (Sandbox Code Playgroud)
现在,希望进一步加速,我实现了一个带有AVX指令集的correpsonding版本:
inline void vector_operation(const size_t i)
{
__m256 X = _mm256_load_ps(x + i);
__m128 yD1 = _mm_cvtpd_ps(_mm_load_pd(yD + i + 0));
__m128 yD2 = _mm_cvtpd_ps(_mm_load_pd(yD + i + 2));
__m128 yD3 = _mm_cvtpd_ps(_mm_load_pd(yD + i + 4));
__m128 yD4 = _mm_cvtpd_ps(_mm_load_pd(yD + i + 6));
__m128 Ylow = _mm_movelh_ps(yD1, yD2);
__m128 Yhigh = _mm_movelh_ps(yD3, yD4);
//Pack __m128 data inside __m256
__m256 Y = _mm256_permute2f128_ps(_mm256_castps128_ps256(Ylow), _mm256_castps128_ps256(Yhigh), 0x20);
//inner-products accumulation
res = _mm256_add_ps(res, _mm256_mul_ps(X, Y));
}
Run Code Online (Sandbox Code Playgroud)
我还测试了其他AVX实现,例如,使用转换和插入操作而不是使用数据进行处理.与x和y向量都是浮动的情况相比,表现相对较差.
AVX代码的问题在于,无论我如何实现它,它的性能远远低于仅使用float x和y向量所实现的性能(即不需要双浮点转换).
对于yD向量,从double到float的转换似乎相当快,而在_m256 Y寄存器中插入数据的行中会丢失大量时间.
你知道这是AVX的一个众所周知的问题吗?
你有一个可以保持良好表现的解决方案吗?
提前致谢!
我重写了您的函数并更好地利用了 AVX 所提供的功能。我还在最后使用了融合乘加;如果您不能使用 FMA,只需用加法和乘法替换该行即可。我现在才看到我编写了一个使用未对齐负载的实现,而您的使用了对齐负载,但我不会因此而失眠。:)
__m256 foo(float*x, double* yD, const size_t i, __m256 res_prev)
{
__m256 X = _mm256_loadu_ps(x + i);
__m128 yD21 = _mm256_cvtpd_ps(_mm256_loadu_pd(yD + i + 0));
__m128 yD43 = _mm256_cvtpd_ps(_mm256_loadu_pd(yD + i + 4));
__m256 Y = _mm256_set_m128(yD43, yD21);
return _mm256_fmadd_ps(X, Y, res_prev);
}
Run Code Online (Sandbox Code Playgroud)
我做了一个快速基准测试,并比较了你和我的实现的运行时间。我尝试了两种不同的基准测试方法并进行了多次重复,每次我的代码速度都提高了 15% 左右。我使用 MSVC 14.1 编译器并使用 /O2 和 /arch:AVX2 标志编译程序。
编辑:这是函数的反汇编:
vcvtpd2ps xmm3,ymmword ptr [rdx+r8*8+20h]
vcvtpd2ps xmm2,ymmword ptr [rdx+r8*8]
vmovups ymm0,ymmword ptr [rcx+r8*4]
vinsertf128 ymm3,ymm2,xmm3,1
vfmadd213ps ymm0,ymm3,ymmword ptr [r9]
Run Code Online (Sandbox Code Playgroud)
编辑2:这是相同算法的AVX实现的反汇编:
vcvtpd2ps xmm0,xmmword ptr [rdx+r8*8+30h]
vcvtpd2ps xmm1,xmmword ptr [rdx+r8*8+20h]
vmovlhps xmm3,xmm1,xmm0
vcvtpd2ps xmm0,xmmword ptr [rdx+r8*8+10h]
vcvtpd2ps xmm1,xmmword ptr [rdx+r8*8]
vmovlhps xmm2,xmm1,xmm0
vperm2f128 ymm3,ymm2,ymm3,20h
vmulps ymm0,ymm3,ymmword ptr [rcx+r8*4]
vaddps ymm0,ymm0,ymmword ptr [r9]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
364 次 |
| 最近记录: |