我想要优化的代码基本上是一个简单但很大的算术公式,自动分析代码以并行计算独立的乘法/加法应该相当简单,但我读到自动向量化仅适用于循环。
我已多次阅读,应该不惜一切代价避免通过联合或其他方式访问向量中的单个元素,而应该替换为_mm_shuffle_pd(我只处理双打)...
我似乎没有想出如何将__m128d向量的内容存储为双精度而不将其作为联合访问。此外,与标量代码相比,这样的操作是否会带来任何性能提升?
union {
__m128d v;
double d[2];
} vec;
union {
__m128d v;
double d[2];
} vec2;
vec.v = index1;
vec2.v = index2;
temp1 = _mm_mul_pd(temp1, _mm_set_pd(bvec[vec.d[1]], bvec[vec2[1]]));
另外,两个工会看起来很丑陋,但在使用时
union dvec {
__m128d v;
double d[2];
} vec;
尝试将indexX声明为dvec,编译器抱怨dvec未声明。
答案 0 :(得分:7)
不幸的是,如果您查看MSDN,它会说以下内容:
您不应直接访问 __m128d字段 。 但是,您可以在调试器中看到这些类型。 __m128类型的变量映射到XMM [0-7]寄存器。
我不是SIMD的专家,但是这告诉我你正在做的事情因为它不适合而无法工作。
编辑:
我只是found this,它说:
仅在赋值的左侧使用__m128,__ m128d和__m128i,作为返回值或作为参数。不要在其他算术表达式中使用它,例如" +"和">>"。
它还说:
在聚合中使用__m128,__ m128d和__m128i对象,例如联合(例如,访问浮点元素)和结构。
所以也许你可以使用它们,但只能在工会中使用它们。然而,似乎与MSDN所说的相矛盾。
<强> EDIT2:强>
Here is another interesting resource that describes with examples on how to use these SIMD types
在上面的链接中,您会找到以下这一行:
#include <math.h>
#include <emmintrin.h>
double in1_min(__m128d x)
{
return x[0];
}
在上面我们使用gcc 4.6中的新扩展来通过索引访问高低部分。较旧版本的gcc需要使用union并写入两个双精度数组。这很麻烦,并且在关闭优化时会非常慢。
答案 1 :(得分:1)
func testme(testArr: [Int], shufflefunction : Shufflefunction = .shuffle) -> [Int] {
return tetsArr.shufflefunction
}
+ _mm_cvtsd_f64
双打:
_mm_unpackhi_pd
对于浮点数,我在How to convert a hex float to a float in C/C++ using _mm_extract_ps SSE GCC instrinc function
上发布了以下示例#include <assert.h>
#include <x86intrin.h>
int main(void) {
__m128d x = _mm_set_pd(1.5, 2.5);
/* _mm_cvtsd_f64 + _mm_unpackhi_pd */
assert(_mm_cvtsd_f64(x) == 2.5);
assert(_mm_cvtsd_f64(_mm_unpackhi_pd(x, x)) == 1.5);
}
+ _mm_cvtss_f32
_mm_shuffle_ps
对于整数,您可以使用_MM_EXTRACT_FLOAT
:
_mm_extract_epi32
编译并运行以下示例:
#include <assert.h>
#include <x86intrin.h>
int main(void) {
__m128i x = _mm_set_epi32(1, 2, 3, 4);
assert(_mm_extract_epi32(x, 3) == 4);
assert(_mm_extract_epi32(x, 2) == 3);
assert(_mm_extract_epi32(x, 1) == 1);
assert(_mm_extract_epi32(x, 0) == 1);
}
在Ubuntu 19.04 amd64上测试。
答案 2 :(得分:0)
在“emmintrin.h”中定义了一个双_mm_cvtsd_f64(__ m128d a)函数来访问两个双精度的sse向量的下半部分。
来自英特尔内在指南:
概要
<强>描述强>: 将a的低位双精度(64位)浮点元素复制到dst。
操作 dst [63:0]:= a [63:0]