我正在尝试使用sse加速我的代码,以下代码运行良好。 基本上__m128变量应该指向一行中的4个浮点数,以便一次执行4个操作。
此代码相当于从c[i]=a[i]+b[i]
到i
计算0
3
。
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]
到i
计算0
3
,它在执行时崩溃。
__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整除的地址。
无论如何,你知道问题是什么以及如何绕过它吗?
答案 0 :(得分: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 :(得分:1)
这里的问题是a
最终指向的不是__m128
;它指向包含__m128
的最后96位和外部32位的东西,可以是任何东西。它可能是下一个__m128
的前32位,但最终,当您到达同一内存块中的最后一个__m128
时,它将是其他内容。也许你无法访问的保留内存,因此崩溃。
答案 2 :(得分:0)
我对sse不太熟悉,但我认为你可以制作一个本地(或另一个副本)数据,这些数据在128处正确分配,并包含4个来自data1 + 1位置的浮点数。
希望这有帮助, 勒兹。