版本 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 block 内调用 func()
函数,例如:
#pragma omp for default(shared) private(i) schedule(static)
for(i=istart;i<istop;i++){
val[i]=func(i);
}
func()
最快且最安全的版本是什么?三个版本都完美无缺吗?
最佳答案
如果我们在函数内部声明静态变量(无论内联与否),编译器将生成一个具有唯一名称的全局变量(通常由函数名和变量名组合而成)。静态函数变量和全局变量之间的区别仅在于可见范围。 所以版本 2 不是线程安全的。
让我们比较一下版本 1 和 3。版本 1 的速度要快一些,因为 X 是一个寄存器,并且不需要将其存储到主存中。速度差异不取决于 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;
}
编译: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)
将结果存储到主存。 X.2782
是我们生成的全局变量。
所以版本 1 更好。
关于c - openmp、内联函数和静态变量(纯 C),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39327541/