我试图说服gcc(4.8.1)或clang(3.4)来对以下内容进行矢量化 常春藤网桥处理器上的代码:
#include "stdlib.h"
#include "math.h"
float sumsqr(float *v, float mean, size_t n) {
float ret = 0;
for(size_t i = 0; i < n; i++) {
ret += pow((v[i] - mean), 2);
}
return ret;
}
并且没有成功编译
$ gcc -std=c99 -O3 -march=native -mtune=native -ffast-math -S foo.c
有没有办法修改代码而不使用instrinsics或修改gcc调用以获得矢量化代码?
答案 0 :(得分:8)
pow
函数非常通用,编译器可能看不到它的作用(请记住它可以计算像pow(1.8, -3.19)
这样的东西。所以它可能只能用于内置操作,并且不进行函数调用:
for(size_t i = 0; i < n; i++)
{
float const x = v[i] - mean;
ret += x * x;
}
答案 1 :(得分:1)
首先,如果你不必,不要使用pow
,简单的乘法让gcc矢量化。现在解释为什么会出现这种行为,请注意用pow
替换powf
,gcc设法进行向量化。 gcc知道pow(x,2)
是x*x
,但问题是pow
是double
的函数。因此编译器必须将数字v[i]-mean
转换为double,将square计算为double,将其作为double添加到ret
,然后才转换为float。如果至少ret
是一个double,那么编译器可以进行矢量化,但是所有这些转换都会使它太复杂而且不值得向量化。