我试图对包含在数学库中使用'pow'函数的循环进行矢量化.我知道英特尔编译器支持使用'pow'作为sse指令 - 但我似乎无法使用gcc运行(我认为).这是我正在使用的情况:
int main(){
int i=0;
float a[256],
b[256];
float x= 2.3;
for (i =0 ; i<256; i++){
a[i]=1.5;
}
for (i=0; i<256; i++){
b[i]=pow(a[i],x);
}
for (i=0; i<256; i++){
b[i]=a[i]*a[i];
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我正在编译以下内容:
gcc -O3 -Wall -ftree-vectorize -msse2 -ftree-vectorizer-verbose=5 code.c -o runthis
Run Code Online (Sandbox Code Playgroud)
这是在使用gcc版本4.2的os X 10.5.8上(我也使用4.5并且无法判断它是否已经向量化了 - 因为它根本没有输出任何内容).似乎没有一个循环矢量化 - 是否存在一个对齐问题或者我需要使用限制的其他问题?如果我将其中一个循环写为函数,我会得到更详细的输出(代码):
void pow2(float *a, float * b, int n) {
int i;
for (i=0; i<n; i++){
b[i]=a[i]*a[i];
}
}
Run Code Online (Sandbox Code Playgroud)
输出(使用7级详细输出):
note: not vectorized: can't determine dependence between *D.2878_13 …Run Code Online (Sandbox Code Playgroud) float pow(float base, int iexp )在C++ 11中删除了重载的函数,现在pow返回一个double.在我的程序中,我计算了很多这些(单精度),我对如何做到最有效的方式感兴趣.
是否有一些特殊功能(在标准库或任何其他)具有上述签名?
如果没有,在任何其他操作(将其他所有内容都投入)或者转换为使用重载函数之前,是否更好(在单精度方面的性能方面)显式地pow转换结果?floatdoubleiexpfloatfloat pow(float base, float exp)
编辑:为什么我需要float和不使用double?
主要原因是RAM - 我需要数十或数百GB,因此这种减少是巨大的优势.所以我需要float得到float.现在我需要最有效的方法来实现这一目标(减少演员阵容,使用已经优化的算法等).
假设我有一个2元素向量定义如下(使用GCC语法打包向量)
// packed vector of 2-elements
typedef double v2d __attribute__((vector_size(sizeof(double)*2)));
v2d x = ...;
double y = ...;
x[0] = pow(x[0], y)
x[1] = pow(x[1], y)
Run Code Online (Sandbox Code Playgroud)
我想知道是否有更快的方法使用向量运算进行两次幂计算.该架构是x86-64上的GCC,平台特定代码是可以的.
在现代x86_64 CPU上,AVX/SSE指数需要多少个时钟周期?
我是这样的: pow(x, y) = exp(y*log(x))
即两者兼而有之exp(),log()AVX x86_64指令需要一定的已知周期数?
_mm256_exp_ps()_mm256_log_ps()或者循环次数可能会根据指数级别而变化,是否有最大循环次数可以进行成本求幂?
我必须多次将 10 提高到两倍的幂。
有没有比使用数学库更有效的方法来做到这一点pow(10,double)?如果重要的话,我的双打总是在 -5 到 -11 之间为负。
我假设 pow(double,double) 使用比 pow(10,double) 所需的更通用的算法,因此可能不是最快的方法。鉴于下面的一些答案,这可能是一个不正确的假设。
至于为什么,是对数插值。我有一个 x 和 y 值表。我的对象有一个已知的 x 值(几乎总是双精度值)。
double Dbeta(struct Data *diffusion, double per){
double frac;
while(per>diffusion->x[i]){
i++;
}
frac = (per-diffusion->x[i-1])/(diffusion->x[i]-diffusion->x[i-1]);
return pow(10,log10DB[i-1] + frac * (log10DB[i]-log10DB[i-1]));
}
Run Code Online (Sandbox Code Playgroud)
这个函数被调用了很多次。我被告知要研究分析,所以这就是我首先要做的。
我刚刚被告知我可以使用自然对数代替以 10 为底的,这显然是正确的。(我的愚蠢有时甚至让我自己感到惊讶。)
用自然对数替换所有内容后,一切都运行得更快了。通过分析(这是我今天学到的一个新词),我发现 39% 的代码都用在了 exp 函数中,所以对于那些想知道这部分是否真的阻碍了我的代码的人来说,它是。