SSE对元素数量不是四的倍数的数组进行处理

SSE works on the array that the number of the elements is not the multiple of four

本文关键字:数组 处理 元素 SSE      更新时间:2023-10-16

每个人。

我的问题是,如果我有三个数组如下

float a[7] = {1.0, 2.0, 3.0, 4.0, 
              5.0, 6.0, 7.0};
float b[7] = {2.0, 2.0, 2.0, 2.0,
              2.0, 2.0, 2.0};
float c[7] = {0.0, 0.0, 0.0, 0.0,
              0.0, 0.0, 0.0};

我想执行元素乘运算如下

c[i] = a[i] * b[i], i = 0, 1, ..., 6

对于前四个元素,我可以使用SSE内部函数,如下

__m128* sse_a = (__m128*) &a[0];
__m128* sse_b = (__m128*) &b[0];
__m128* sse_c = (__m128*) &c[0];
*sse_c = _mm_mul_ps(*sse_a, *sse_b);

c中的内容将是

c[0] = 2.0, c[1] = 4.0, c[2] = 6.0, c[3] = 8.0
c[4] = 0.0, c[5] = 0.0, c[6] = 0.0

索引4、5和6中剩下的三个数字,我使用以下代码执行元素乘运算

sse_a = (__m128*) &a[4];
sse_b = (__m128*) &b[4];
sse_c = (__m128*) &c[4];
float mask[4] = {1.0, 1.0, 1.0, 0.0};
__m128* sse_mask = (__m128*) &mask[0];
*sse_c = _mm_add_ps( *sse_c, 
    _mm_mul_ps( _mm_mul_ps(*sse_a, *sse_b), *sse_mask ) );

并且c[4-6]中的内容将是

c[4] = 10.0, c[5] = 12.0, c[6] = 14.0, which is the expected result.

_mm_add_ps((将四个浮点并行相加,第一个、第二个和第三个浮点数分别分配在数组a、b和c的索引4、5和6中。但是第四个浮点数没有分配给数组。为了避免无效的内存访问,我在sse_mask上相乘,使第四个数字为零,然后将结果加回sse_c(数组c(。

但我想知道它是否安全?

非常感谢。

您似乎有正确的数学运算,但我真的不确定像您这样使用强制转换是否是在__m128变量中加载和存储数据的方法。

装载和储存

要将数据从数组加载到__m128变量,应使用__m128 _mm_load_ps (float const* mem_addr)__m128 _mm_loadu_ps (float const* mem_addr)。很容易弄清楚这里是什么,但有一些精确性:

  • 对于涉及内存访问或操作的操作,通常有两个函数在做相同的事情,例如loadloadu。第一种要求内存在16字节的边界上对齐,而u版本则没有这一要求。如果您不了解内存对齐,请使用u版本
  • 您还有load_psload_pd。区别:s代表单精度中的单精度(好的旧float(,d代表双精度中的双精度。当然,每个__m128变量只能放入两个double,但可以放入4个float

因此,从数组中加载数据非常容易,只需执行以下操作即可:__m128* sse_a = _mm_loadu_ps(&a[0]);。对b也这样做,但对c来说,这真的取决于情况。如果你只想有乘法的结果,那么把它初始化为0,加载它,然后把乘法的结果加到它上,最后把它拿回来是没有用的。

您应该使用load的挂起操作来存储数据,即void _mm_storeu_ps (float* mem_addr, __m128 a)。因此,一旦多应用程序完成并在sse_c中得到结果,只需执行_mm_storeu_ps(&c[0@, sse_c) ;

算法

使用掩码背后的想法很好,但您有一些更简单的东西:从a[3]加载和存储数据(对于b和c也是如此(。这样,它将有4个元素,所以不需要使用任何口罩?是的,已经对第三个元素进行了一次操作,但这将是完全透明的:store操作只会用新值替换旧值。既然两者相等,那就不是问题。

一种选择是在数组中存储8个元素,即使您只需要7个。这样,你就不必担心内存是否被分配,也不需要像上面这样的特殊逻辑来支付3个浮点的成本,这在所有最近的计算机上都不算什么。