【问题标题】:Using SSE to speed up computation - store, load and alignment使用 SSE 加速计算 - 存储、加载和对齐
【发布时间】:2011-02-25 14:06:25
【问题描述】:

在我的项目中,我实现了基本类 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;  
    }
}

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

【问题讨论】:

    标签: c++ sse


    【解决方案1】:

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

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

    【讨论】:

    • 现代架构不再那么昂贵了。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2016-10-10
      • 1970-01-01
      • 2013-11-12
      • 2015-07-31
      • 2017-04-16
      • 2012-03-04
      • 1970-01-01
      • 2017-11-11
      • 1970-01-01
      相关资源
      最近更新 更多