【发布时间】:2012-02-14 05:27:25
【问题描述】:
我们有一个 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 会发生什么?这会导致customPow.o 中的pow 和libc 中的pow 之间的命名冲突吗?
【问题讨论】:
-
很好的 Fortran!有趣的问题虽然 +1