使用SSE加速计算 - 存储,加载和对齐

时间:2011-02-25 14:06:26

标签: c++ sse

在我的项目中,我实现了基本的类CVector。 该类包含指向原始浮点数组的float *指针。 使用标准malloc()函数动态分配此数组。

现在我必须使用这样的向量加速一些计算。不幸的是,由于内存未使用_mm_malloc()进行分配,因此未对齐。

据我所知,我有两种选择:

1)重写代码,分配内存以使用_mm_malloc(),例如使用如下代码:

void sub(float* v1, float* v2, float* v3, int size) 
{  
    __m128* p_v1 = (__m128*)v1;  
    __m128* p_v2 = (__m128*)v2;  
    __m128 res;

    for(int i = 0; i < size/4; ++i)  
    {  
        res = _mm_sub_ps(*p_v1,*p_v2);  
        _mm_store_ps(v3,res);  
        ++p_v1;  
        ++p_v2;  
        v3 += 4;  
    }
}

2)第二个选项是使用_mm_loadu_ps()指令从未对齐的内存加载__m128,然后将其用于计算。

void sub(float* v1, float* v2, float* v3, int size)
{  
    __m128 p_v1;  
    __m128 p_v2;  
    __m128 res;

    for(int i = 0; i < size/4; ++i)  
    {  
        p_v1 = _mm_loadu_ps(v1);   
        p_v2 = _mm_loadu_ps(v2);  
        res = _mm_sub_ps(p_v1,p_v2);    
        _mm_store_ps(v3,res);  
        v1 += 4;  
        v2 += 4;  
        v3 += 4;  
    }
}

所以我的问题是哪个选项更好或更快?

2 个答案:

答案 0 :(得分:15)

读取未对齐的SSE值非常昂贵。查看英特尔手册,第4卷,第2.2.5.1章。核心类型有所不同,i7具有额外的硬件,使其成本更低。但是读取跨越cpu缓存行边界的值仍然比读取对齐值慢4.5倍。在之前的架构中,它的速度要慢十倍。

这是巨大的,让内存对齐以避免这种性能。从未听说过_mm_malloc,请使用Microsoft CRT中的_aligned_malloc()从堆中获取正确对齐的内存。

答案 1 :(得分:1)

看看bullet physics。它被用于少数电影和知名游戏(GTA4和其他)。你可以看看他们的超级优化矢量,矩阵和其他数学类,或者只是使用它们。它是在zlib许可下发布的,所以你可以随意使用它。不要重新发明轮子。 Bullet,nvidia physx,havok和其他物理库经过了很好的测试和优化,非常聪明的人