tpg*_*114 24 c fortran libc pow
我们有一个CFD求解器,在运行模拟时,发现它在某些机器上运行速度非常慢,而在其他机器上却运行得非常慢.使用英特尔VTune,发现以下行是问题(在Fortran中):
RHOV= RHO_INF*((1.0_wp - COEFF*EXP(F0)))**(1.0_wp/(GAMM - 1.0_wp))
Run Code Online (Sandbox Code Playgroud)
使用VTune进行钻取,问题可以追溯到call pow装配线,当跟踪堆栈时,它显示它正在使用__slowpow().经过一番搜索,这个页面出现了抱怨同样的事情.
在具有libc版本2.12的机器上,模拟花了18秒.在libc版本为2.14的机器上,模拟耗时0秒.
基于上述页面的信息,当基数pow()接近1.0 时出现问题.所以我们做了另一个简单的测试,我们在之前用任意数字缩放基数pow(),然后除以在pow()调用之后提升到指数的数字.使用libc 2.12时,运行时间从18秒减少到0秒.
但是,将这些全部放在我们所做的代码上是不切实际的a**b.如何更换pow()libc中的函数?例如,我希望call powFortran编译器生成的装配线调用pow()我们编写的自定义函数来执行缩放,调用libc pow()然后除以缩放.如何创建一个对编译器透明的中间层?
编辑
为了澄清,我们正在寻找类似(伪代码)的东西:
double pow(a,b) {
a *= 5.0
tmp = pow_from_libc(a,b)
return tmp/pow_from_libc(5.0, b)
}
Run Code Online (Sandbox Code Playgroud)
是否可以加载powlibc并在我们的自定义函数中重命名以避免命名冲突?如果customPow.o文件可以pow从libc 重命名,如果其他东西仍然需要libc会发生什么?这会导致libc pow中customPow.o和powlibc 之间的命名冲突吗?
Jon*_*rsi 22
那么,坚持吧.图书馆不仅仅是打电话__slowpow()给你玩具; 它正在调用,__slowpow()因为它认为额外的精度对于给出你给它的值给出一个准确的结果是必要的(在这种情况下,基数非常接近1,指数为1).如果你关心这个计算的准确性,你应该理解为什么会这样,如果在尝试解决它之前它是否重要.可能是这样的情况,对于(比方说)大的负F0,整个事情可以安全地舍入到1; 或者它可能不会,取决于稍后对此值的处理方式.如果您需要1.d0减去此结果,您将需要额外的精度.
只需编写自己的pow函数,将.o文件libmypow.a放在链接器库路径中的某个静态库存档中,并-lmypow在链接时传递.