我有两个double类型的数组,我想执行vecA += vecB。到目前为止,我正在做vecA = vecA + vecB,据我所知,例如写入i = i + 5的整数比i += 5慢。所以我想知道,是否有一些SSE函数可以在__m128d上仅执行operator+=。我搜索后什么也没找到。我的应用程序在vecA = vecA + vecB操作上花费了大约60%的时间,因此任何性能提升都会显示出来。

下面的代码片段中的所有数组都是16字节对齐的,len始终是偶数。

原始代码很简单

inline void addToDoubleVectorSSE(
         const double * what, const double * toWhat, double * dest, const unsigned int len)
{
   __m128d * _what      = (__m128d*)what;
   __m128d * _toWhat    = (__m128d*)toWhat;

   for ( register unsigned int i = 0; i < len; i+= 2 )
   {
       *_toWhat = _mm_add_pd( *_what, *_toWhat );
       _what++;
       _toWhat++;
   }
}

在阅读http://fastcpp.blogspot.cz/2011/04/how-to-process-stl-vector-using-sse.html之后,作者通过不立即写他刚刚阅读的内容而获得了表现,因此我尝试了
__m128d * _what         = (__m128d*)what;
__m128d * _toWhat       = (__m128d*)toWhat;
__m128d * _toWhatBase   = (__m128d*)toWhat;

__m128d _dest1;
__m128d _dest2;

for ( register unsigned int i = 0; i < len; i+= 4 )
{
    _toWhatBase = _toWhat;
    _dest1      = _mm_add_pd( *_what++, *_toWhat++ );
    _dest2      = _mm_add_pd( *_what++, *_toWhat++ );

    *_toWhatBase++ = _dest1;
    *_toWhatBase++ = _dest2;
}

但是速度没有任何改善。那么,operator+=是否有任何__m128d?还是我可以使用其他方法对双精度数组执行operator + =?使用MSVC,目标平台将始终是Intel i7 CPU上的Windows(XP和7)。

最佳答案

据我所知,没有等效的+=,因为SSE算术运算通常是寄存器到寄存器或内存到寄存器的,而不是寄存器到内存的。

但是,您可以使用链接的博客文章中的建议来提高性能。该技巧对您无效的原因是您没有消除两条指令之间的依赖关系:++_what++_toWhat++增量的副作用阻止了第二对操作同时开始。如下修改您的循环以获得改进:

for ( register unsigned int i = 0; i < len; i+= 4, _what += 2, _toWhat += 2, _toWhatBase+=2 )
{
    _toWhatBase = _toWhat;
    _dest1      = _mm_add_pd( *_what, *_toWhat );
    _dest2      = _mm_add_pd( *(_what+1), *(_toWhat+1));

    *_toWhatBase = _dest1;
    *(_toWhatBase+1) = _dest2;
}

更改后,对_dest2的操作变得独立于对_dest1的操作

根据我的挂钟估计,经过简单的修改,我的性能提高了约28%。

09-17 09:29