【发布时间】:2017-02-18 05:51:16
【问题描述】:
考虑执行相同计算的这三个函数:
#include <x86intrin.h>
void testfunc_loop(double a, double b, double* dst)
{
double f[] = {a,b,-a,-b};
for(int n = 0; n < 4; ++n)
{
dst[n] = 0.1 + f[n]*(1.0 + 0.5*f[n]);
}
}
void testfunc_flat(double a, double b, double* dst)
{
dst[0] = 0.1 + ( a)*(1.0 + 0.5*( a));
dst[1] = 0.1 + ( b)*(1.0 + 0.5*( b));
dst[2] = 0.1 + (-a)*(1.0 + 0.5*(-a));
dst[3] = 0.1 + (-b)*(1.0 + 0.5*(-b));
}
void testfunc_avx(double a, double b, double* dst)
{
__m256d one = _mm256_set1_pd(1.0);
__m256d half = _mm256_set1_pd(0.5);
__m256d tenth = _mm256_set1_pd(0.1);
__m256d v = _mm256_set_pd(-b,-a,b,a);
__m256d q = _mm256_add_pd(tenth,_mm256_mul_pd(v,_mm256_add_pd(one,_mm256_mul_pd(half,v))));
_mm256_store_pd(dst,q);
}
GCC 4.7.2(带有 -O3 -mavx)对循环版本进行矢量化,但对展开的循环使用标量操作。三个版本所采用的(标准化)时间分别为 3.3(循环、自动矢量化)、1.2(展开、标量)、1(手动 avx)。展开版本和手动矢量化函数之间的性能差异很小,但我想强制矢量化,因为它对完整代码有益。
用不同的编译器进行测试(参见https://godbolt.org/g/HJH2CX)表明clang 会自动对展开的循环进行矢量化(从版本3.4.1 开始),但直到版本7 的GCC 却没有。我可以使用 GCC 自动获得类似的矢量化吗?我只发现与循环矢量化相关的优化选项无济于事。 GCC website 显示自 2011 年以来没有任何消息。
【问题讨论】:
-
请注意,在 gcc 的 bugzilla 中为错过的优化提交问题是明智的做法。 AVX 矢量化失败,因为带有/不带有否定的表达式看起来与 gcc 太不同了。另一方面,它几乎做了 SSE 向量化,但拒绝它是无利可图的(使用 -fvect-cost-model=unlimited 来查看它会产生什么),因为它严重高估了序言成本(它构建了向量 {a,b } 至少 3 次,{1,1} 两次等)。
-
gcc.gnu.org/bugzilla/show_bug.cgi?id=78164 用于 llvm 获得但不是 gcc 的 testfunc_flat 的 SSE 矢量化。
标签: gcc clang sse avx auto-vectorization