在我的项目中,我实现了基本的类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;
}
}
所以我的问题是哪个选项更好或更快?
答案 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和其他物理库经过了很好的测试和优化,非常聪明的人