我想编写快速的simd代码来计算复杂数组的乘法减少.在标准C中,这是:
#include <complex.h>
complex float f(complex float x[], int n ) {
complex float p = 1.0;
for (int i = 0; i < n; i++)
p *= x[i];
return p;
}
Run Code Online (Sandbox Code Playgroud)
n 将最多50.
Gcc不能自动矢量化复数乘法但是,因为我很乐意假设gcc编译器,如果我知道我想要定位sse3,我可以按照如何在gcc中启用sse3自动向量化并写入:
typedef float v4sf __attribute__ ((vector_size (16)));
typedef union {
v4sf v;
float e[4];
} float4
typedef struct {
float4 x;
float4 y;
} complex4;
static complex4 complex4_mul(complex4 a, complex4 b) {
return (complex4){a.x.v*b.x.v -a.y.v*b.y.v, a.y.v*b.x.v + a.x.v*b.y.v};
}
complex4 f4(complex4 x[], int n) …Run Code Online (Sandbox Code Playgroud) 考虑这个简单的代码:
#include <complex.h>
complex float f(complex float x) {
return x*x;
}
Run Code Online (Sandbox Code Playgroud)
如果-O3 -march=core-avx2 -fp-model strict使用英特尔编译器进行编译,则可以获得:
f:
vmovsldup xmm1, xmm0 #3.12
vmovshdup xmm2, xmm0 #3.12
vshufps xmm3, xmm0, xmm0, 177 #3.12
vmulps xmm4, xmm1, xmm0 #3.12
vmulps xmm5, xmm2, xmm3 #3.12
vaddsubps xmm0, xmm4, xmm5 #3.12
ret
Run Code Online (Sandbox Code Playgroud)
这比从两者中获得的代码简单得多gcc,clang而且比在线复制数字的代码简单得多.例如,它没有明确地用于处理复杂的NaN或无穷大.
这个组件是否符合C99复数乘法的规范?
我正在寻找一种快速计算含有3或4个成分的向量的点积的方法.我尝试了几件事,但大多数在线示例都使用了一系列浮点数,而我们的数据结构却不同.
我们使用16字节对齐的结构.代码摘录(简化):
struct float3 {
float x, y, z, w; // 4th component unused here
}
struct float4 {
float x, y, z, w;
}
Run Code Online (Sandbox Code Playgroud)
在之前的测试中(使用SSE4点积本征或FMA)与使用以下常规c ++代码相比,我无法获得加速.
float dot(const float3 a, const float3 b) {
return a.x*b.x + a.y*b.y + a.z*b.z;
}
Run Code Online (Sandbox Code Playgroud)
在英特尔Ivy Bridge/Haswell上使用gcc和clang进行测试.似乎花费时间将数据加载到SIMD寄存器并再次将其拉出会消耗所有的好处.
我将非常感谢一些帮助和想法,如何使用我们的float3/4数据结构有效地计算点积.SSE4,AVX甚至AVX2都没问题.
提前致谢.