2013-10-15 29 views
0

我试图加快使用SSE我的代码,然后将以下代码效果很好。 基本上,__m128变量应该指向一行中的4个浮点数,以便一次执行4个操作。解决非整数的地址,和SSE

此代码相当于计算c[i]=a[i]+b[i]i03

float *data1,*data2,*data3 
// ... code ... allocating data1-2-3 which are very long. 
__m128* a = (__m128*) (data1); 
__m128* b = (__m128*) (data2); 
__m128* c = (__m128*) (data3); 
*c = _mm_add_ps(*a, *b); 

然而,当欲移位一个比特,我使用的数据(见下文),以计算与c[i]=a[i+1]+b[i]i03,它在craches执行时间。

__m128* a = (__m128*) (data1+1); // <-- +1 
__m128* b = (__m128*) (data2); 
__m128* c = (__m128*) (data3); 
*c = _mm_add_ps(*a, *b); 

我的猜测是它与__m128是128位,浮点数据是32位有关。因此,它可能是不可能的128位指针指向的不是整除128

反正地址,你知道是什么问题,我怎么可能去走一走呢?

+2

您有未定义的行为。指向'float'的指针与* __m128指针不同*。另外,当你执行'data1 + 1'和'&data1 [1]'做同样的事情时,你真的已经分配了多个'float'并将指针存储在'data1'中吗? –

+0

是的,data1,data2,data3中有很多数据。他们分配得很好。 – Oli

+0

@JoachimPileborg,什么是无约束的行为?我知道指向float和__m128的指针是不同的。这就是我投的原因。 __mm128应该指向连续4个浮点数,以便在CPU上一次执行所有4个操作。 – Oli

回答

5

代替使用隐式对齐的加载/存储这样的:

__m128* a = (__m128*) (data1+1); // <-- +1 
__m128* b = (__m128*) (data2); 
__m128* c = (__m128*) (data3); 
*c = _mm_add_ps(*a, *b); 

使用显式对准/未对齐加载/存储酌情例如:

__m128 va = _mm_loadu_ps(data1+1); // <-- +1 (NB: use unaligned load) 
__m128 vb = _mm_load_ps(data2); 
__m128 vc = _mm_add_ps(va, vb); 
_mm_store_ps(data3, vc); 

的代码相同的量(即相同数量的的指令),但它不会崩溃,并且您可以明确控制哪些加载/存储已对齐,哪些未对齐。

需要注意的是近期CPU具有不对齐的负荷相对较小的处罚,但在旧的CPU可以有2倍或更大的打击。

+1

谢谢。它适用于我的情况,它没有什么开销。 – Oli

+1

有时洗牌然后对齐访问可能比未对齐的加载/存储更快 –

0

我不是很熟悉,SSE,但我想你就可以说是正常的128神韵:和包含数据1 + 1点的位置4个浮点数据的本地(或另一个副本)。

希望这有助于 勒兹万。

+0

谢谢。这肯定会奏效。但是,sse的重要性也让一切都变得非常快。如果我必须先复制,它会比不使用sse慢。 – Oli

+0

@Oli您可能需要先对其进行基准测试。复制16个字节非常快。 –

1

你这里的问题是,a最终指向的东西是不是一个__m128;它指向的东西包含__m128的最后96位和外部32位,可以是任何东西。它可能是下一个__m128的前32位,但最终,当你在同一个内存块中到达最后的__m128时,它将是别的。也许保留的内存,你不能访问,因此崩溃。