【发布时间】:2019-03-18 12:25:41
【问题描述】:
我无法理解如何使用 SSE 内在函数将一些 SIMD 计算的结果存储回“正常变量”。例如 _mm_store_ps 内在函数在“Intel Intrinsics Guide”中描述如下:
void _mm_store_ps (float* mem_addr, __m128 a)
存储 128 位(由 4 个打包单精度(32 位)组成) 浮点元素)从 a 到内存。 mem_addr 必须对齐 在 16 字节边界上或一般保护异常可能是 生成。
第一个参数是一个指针,指向一个大小为 32 位的浮点数。但描述指出,内在函数会将 128 位从 a 复制到目标 mem_addr。
- mem_addr 是否需要为 4 个浮点数的数组?
- 如何仅访问 a 中的特定 32 位元素并将其存储在单个浮点数中?
- 我在概念上缺少什么?
- 还有比 _mm_store_ps 内在函数更好的选择吗?
这是一个简单的结构,其中 doSomething() 将 1 加到结构的 x/y 上。缺少的是关于如何将结果存储回 x/y 的部分,而仅使用较高的 32 位宽元素 2 和 3,而未使用 1 和 0。
struct vec2 {
union {
struct {
float data[2];
};
struct {
float x, y;
};
};
void doSomething() {
__m128 v1 = _mm_setr_ps(x, y, 0, 0);
__m128 v2 = _mm_setr_ps(1, 1, 0, 0);
__m128 result = _mm_add_ps(v1, v2);
// ?? How to store results in x,y ??
}
}
【问题讨论】:
-
使用
_mm_store_sd对向量的低半部分进行 64 位存储。或_mm_storel_pi(movlps)。除了_mm_setr,您可以使用_mm_load_sd((float*)&vec.x)进行零扩展为128 位向量的64 位加载。 -
mem_addr不需要声明为float[],但需要正确对齐,这可以通过_mm_malloc或aligned_malloc等对齐分配来完成,尽管@987654332 @ 应该已经分配给alignof(std::max_align_t)字节。如果数据不是动态分配的,那么应该使用alignas关键字(例如在vec2类型的data字段上)。
标签: c++ sse simd intrinsics