c++ - SSE作用于元素个数不是4的倍数的数组

标签 c++ arrays memory-management sse intrinsics

每个人。

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

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() 并行添加四个 float ,第一、第二、第三个 float 分别分配在数组a、b、c的索引4、5、6处。 但是第四个 float 没有分配给数组。 为了避免无效的内存访问,我乘以 sse_mask 使第四个数字为零,然后将结果添加回 sse_c(数组 c)。

但我想知道它是否安全?

非常感谢。

最佳答案

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

加载和存储

要将数组中的数据加载到 __m128 变量,您应该使用 __m128 _mm_load_ps (float const* mem_addr)__m128 _mm_loadu_ps (float const*内存地址) 。很容易弄清楚这里是什么,但需要一些精确度:

  • 对于涉及内存访问或操作的操作,通常有两个函数做同样的事情,例如 loadloadu 。第一个要求你的内存在 16 字节边界上对齐,而 u 版本没有这个要求。如果您不了解内存对齐,请使用 u 版本。
  • 您还有 load_psload_pd。区别:s 代表单精度(好旧的 float),d 代表 double ,即 double 。当然,每个 __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 个元素,那么就不需要使用任何 mask 了?是的,已经对第三个元素进行了一项操作,但这将是完全透明的:store 操作只会用新值替换旧值。因为两者是平等的,所以这不是问题。

一种替代方法是在你的数组中存储 8 个元素,即使你只需要 7 个元素。这样你就不必担心内存是否被分配,不需要像上面那样的特殊逻辑来支付 3 个 float 的成本,这在所有最近的计算机上都没有。

关于c++ - SSE作用于元素个数不是4的倍数的数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39384037/

相关文章:

c++ - std::bind pre-C++11 的替代方案

c++ - 从其单元格小部件项中检索父 QTableWidget

c - 更新我的阵列棋盘游戏

arrays - R填充多维数组

c - malloc() : memory corruption

zlib压缩数据时的内存分配?

c++ - AddRef 和函数签名

c++ - 不能在类外定义类函数

arrays - 算法分析 - 在排序数组中查找丢失的整数优于 O(n)

php memory_get_usage(true) vs top %MEM