Tho*_*mas 7 c++ gcc simd clang
我正在寻找一种快速计算含有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都没问题.
提前致谢.
从代数上讲,高效的 SIMD 看起来几乎与标量代码相同。因此,进行点积的正确方法是一次对四个浮点向量进行操作以进行 SEE(使用 AVX 时为八个)。
考虑像这样构建你的代码
#include <x86intrin.h>
struct float4 {
__m128 xmm;
float4 () {};
float4 (__m128 const & x) { xmm = x; }
float4 & operator = (__m128 const & x) { xmm = x; return *this; }
float4 & load(float const * p) { xmm = _mm_loadu_ps(p); return *this; }
operator __m128() const { return xmm; }
};
static inline float4 operator + (float4 const & a, float4 const & b) {
return _mm_add_ps(a, b);
}
static inline float4 operator * (float4 const & a, float4 const & b) {
return _mm_mul_ps(a, b);
}
struct block3 {
float4 x, y, z;
};
struct block4 {
float4 x, y, z, w;
};
static inline float4 dot(block3 const & a, block3 const & b) {
return a.x*b.x + a.y*b.y + a.z*b.z;
}
static inline float4 dot(block4 const & a, block4 const & b) {
return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
}
Run Code Online (Sandbox Code Playgroud)
请注意,最后两个函数看起来与您的标量dot函数几乎相同,只是float变成float4和float4变成block3或block4。这将最有效地进行点积。