版本1:
inline double func(int i){
double X;
X=sqrt(2)*i;
return X;
}
版本2:
inline double func(int i){
static double X;
X=sqrt(2)*i;
return X;
}
版本3:
inline double func(int i){
static double X;
#pragma omp threadprivate(X)
X=sqrt(2)*i;
return X;
}
然后在openmp块内调用func()
函数,例如:
#pragma omp for default(shared) private(i) schedule(static)
for(i=istart;i<istop;i++){
val[i]=func(i);
}
func()
最快,最安全的版本是什么?这三个版本都完美无缺吗?
答案 0 :(得分:0)
如果我们在函数内部声明一个静态变量(内联与否无关),编译器将生成一个具有唯一名称的全局变量(通常由函数名和变量名组合而成)。静态函数变量和全局变量之间的区别仅在于可见性范围。 所以版本2不是线程安全的。
让我们比较版本1和3.由于X是一个寄存器,版本1有点快,并且没有必要将它存储到主存储器中。速度差异不依赖于inline
或openmp
,因此我将展示一个更简单的示例:
#include <math.h>
double func1(int i){
double X;
X=M_SQRT2*i;
return X;
}
double func2(int i){
static double X;
X=M_SQRT2*i;
return X;
}
编译:{{1}}
此处gcc -S -O3 test.c
用于生成汇编程序文件-S
,而test.s
用于启用优化。
-O3
我们可能会发现func1:
.LFB3:
.cfi_startproc
cvtsi2sd %edi, %xmm0
mulsd .LC0(%rip), %xmm0
ret
.cfi_endproc
func2:
.LFB4:
.cfi_startproc
cvtsi2sd %edi, %xmm0
mulsd .LC0(%rip), %xmm0
movsd %xmm0, X.2782(%rip)
ret
.cfi_endproc
更长一行。
指令func2
将结果存储到主存储器中。 movsd %xmm0, X.2782(%rip)
是我们生成的全局变量。
因此版本1更好。