1

我正在尝试使用 SSE 加速我的代码,以下代码运行良好。基本上,一个__m128变量应该连续指向 4 个浮点数,以便一次执行 4 个操作。

此代码等效于c[i]=a[i]+b[i]使用ifrom 0to进行计算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]使用ifrom 0to进行计算时3,它会在执行时崩溃。

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

我的猜测是它与__m128128 位和float数据是 32 位的事实有关。因此,一个 128 位指针可能不可能指向一个不能被 128 整除的地址。

无论如何,您知道问题出在哪里以及我该如何解决吗?

4

2 回答 2

6

而不是像这样使用隐式对齐的加载/存储:

__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 倍或更大的命中。

于 2013-10-15T10:02:57.417 回答
0

您的问题是a最终指向的东西不是__m128; 它指向包含 an 的最后 96 位__m128和外部 32 位的东西,可以是任何东西。它可能是 next 的前 32 位__m128,但最终,当您到达__m128同一内存块中的最后一个时,它将是另一回事。也许您无法访问的保留内存,因此崩溃。

于 2013-10-15T08:29:26.303 回答