我们有一个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/

10-11 23:08
查看更多