我们有一个 CFD 求解器,在运行模拟时,发现它在某些机器上运行异常缓慢,但在其他机器上却没有。使用 Intel VTune,发现以下行是问题(在 Fortran 中):
RHOV= RHO_INF*((1.0_wp - COEFF*EXP(F0)))**(1.0_wp/(GAMM - 1.0_wp))
用 VTune 钻取,问题被追溯到call pow
装配线,当跟踪堆栈时,它显示它正在使用__slowpow()
. 经过一番搜索,这个页面出现了抱怨同样的事情。
在具有 libc 版本 2.12 的机器上,模拟耗时 18 秒。在具有 libc 版本 2.14 的机器上,模拟耗时 0 秒。
根据上述页面上的信息,当 base topow()
接近 1.0 时会出现问题。所以我们做了另一个简单的测试,我们在之前用任意数字缩放基数,pow()
然后除以pow()
调用之后的指数。这也将 libc 2.12 的运行时间从 18 秒降至 0 秒。
然而,把它放在我们做的所有代码中是不切实际的a**b
。如何替换pow()
libc 中的函数?例如,我希望call pow
Fortran 编译器生成的装配线调用pow()
我们编写的自定义函数来进行缩放,调用 libc pow()
,然后除以缩放。如何创建对编译器透明的中间层?
编辑
为了澄清,我们正在寻找类似(伪代码)的东西:
double pow(a,b) {
a *= 5.0
tmp = pow_from_libc(a,b)
return tmp/pow_from_libc(5.0, b)
}
是否可以从 libc 加载pow
并在我们的自定义函数中重命名以避免命名冲突?如果customPow.o
文件可以pow
从 libc 重命名,如果其他事情仍然需要 libc 会发生什么?这会导致libcpow
中customPow.o
的命名冲突吗?pow