我注意到在不使用技巧的情况下__m128
可以按索引访问字段。gcc
union
__m128 t;
float r(t[0] + t[1] + t[2] + t[3]);
我也可以__m128
像数组一样加载:
__m128 t{1.f, 2.f, 3.f, 4.f};
这一切都符合gcc
' 向量扩展。但是,这些可能在其他地方不可用。intel 编译器和 msvc 是否支持加载和访问功能?
我注意到在不使用技巧的情况下__m128
可以按索引访问字段。gcc
union
__m128 t;
float r(t[0] + t[1] + t[2] + t[3]);
我也可以__m128
像数组一样加载:
__m128 t{1.f, 2.f, 3.f, 4.f};
这一切都符合gcc
' 向量扩展。但是,这些可能在其他地方不可用。intel 编译器和 msvc 是否支持加载和访问功能?
如果你想让你的代码在其他编译器上工作,那么不要使用那些 GCC 扩展。使用 set/load/store 内在函数。 _mm_setr_ps
可以设置常量值,但不应该在循环中使用。要访问元素,我通常先将值存储到数组中,然后再读取数组。
如果你有一个数组a
,你应该读取/存储它
__m128 t = _mm_loadu_ps(a);
_mm_storeu_ps(a, t);
如果数组是 16 字节对齐的,您可以使用对齐的加载/存储,这在新系统上稍快,但在旧系统上快得多。
__m128 t = _mm_load_ps(a);
_mm_store_ps(a, t);
要在堆栈上获得 16 字节对齐的内存,请使用
__declspec(align(16)) const float a[] = ...//MSVC
__attribute__((aligned(16))) const float a[] ...//GCC, ICC
对于 16 字节对齐的动态数组,请使用:
float *a = (float*)_mm_malloc(sizeof(float)*n, 16); //MSVC, GCC, ICC, MinGW
您也可以为此使用宏:
//Test to see if we are using MSVC as MSVC AVX types are slightly different to the GCC ones
#ifdef _MSC_VER
#define GET_F32_AVX_MULTIPLATTFORM(vector,index) (vector).m256_f32[index]
#define GET_F64_AVX_MULTIPLATTFORM(vector,index) (vector).m256d_f64[index]
#else
#define GET_F32_AVX_MULTIPLATTFORM(vector,index) (vector)[index]
#define GET_F64_AVX_MULTIPLATTFORM(vector,index) (vector)[index]
#endif
要加载__m128
,您可以编写_mm_setr_ps(1.f, 2.f, 3.f, 4.f)
,GCC、ICC、MSVC 和 clang 都支持。
据我所知,clang 和最新版本的 GCC 支持__m128
按索引访问字段。我不知道如何在 ICC 或 MSVC 中执行此操作。我猜_mm_extract_ps
它适用于所有 4 个编译器,但它的返回类型很疯狂,使用起来很痛苦。