我们有一个CFD求解器,在运行模拟时,发现它在某些机器上运行异常缓慢,而在其他机器上运行却异常缓慢。使用Intel VTune,发现以下行是问题所在(在Fortran中):
RHOV= RHO_INF*((1.0_wp - COEFF*EXP(F0)))**(1.0_wp/(GAMM - 1.0_wp))
使用VTune进行钻探,问题被追溯到
call pow
装配线,并且在跟踪堆栈时,它表明它正在使用__slowpow()
。经过一番搜索,this page出现了抱怨同一件事的信息。在具有libc版本2.12的计算机上,模拟花费了18秒。在具有libc版本2.14的计算机上,模拟花费了0秒。
根据上述页面上的信息,当
pow()
的底数接近1.0时会出现问题。因此,我们做了另一个简单的测试,在pow()
之前将基数按任意数字缩放,然后在pow()
调用后除以加到指数的数字。对于libc 2.12,这也将运行时间从18秒降低到0秒。但是,将其全部放置在我们执行
a**b
的代码中是不切实际的。如何替换libc中的pow()
函数?例如,我希望由Fortran编译器生成的组装线call pow
调用我们编写的自定义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
文件可以从libc重命名pow
,那么如果还需要libc做其他事情怎么办?这会导致pow
中的customPow.o
和libc中的pow
之间的命名冲突吗? 最佳答案
只需编写自己的pow
函数,将.o
文件放在链接程序库路径中某个位置的静态库存档libmypow.a
中,然后在链接时传递-lmypow
。
关于c - 替换异常慢的pow()函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9272155/