如何解决为什么“自我时间”在一个有效的空函数中如此之高?
program array_initialize
implicit none
integer :: i,j,limit
real :: my_max
real :: start,finish
my_max = -1.0
limit = 10000
call cpu_time(start)
do j=1,limit
do i=1,limit
my_max = max(my_max,initializer(i,j))
end do
end do
call cpu_time(finish)
print *,my_max
print '("Time = ",f6.3," seconds.")',finish-start
contains
function initializer(i,j)
implicit none
real :: initializer
real :: arr(2)
integer :: i,j
arr(1) = -1.0/(2*i+j+1)
arr(2) = -1.0/(2*j+i+1)
initializer = max(arr(1),arr(2))
end function
end program array_initialize
当我使用 Chrome 的 DevTools 分析这个脚本时,我得到了这个:
function func() { // Some fluff
for(let i = 0; i < 1000; i++) {
i *= 10
i /= 10
}
}
function run() {
for(let i = 0; i < 100000; i++) {
func()
}
}
run()
在 1015 毫秒的总时间中拥有 887 毫秒的自我时间,即使它唯一做的就是重复调用 run
。
这是为什么?
解决方法
(此处为 V8 开发人员。)
该函数在变得“热”一段时间后自动内联。
正确。 run
一经优化,优化器就决定将 func
内联到其中。之后,就profiler而言,所有的时间都花在了run
上。
(要验证这一点,请使用 d8
在 node
或 --trace-turbo-inlining
中运行代码段。)
旁注:在这种情况下,获得 run
的优化代码需要比平时更长的时间,因为该函数永远不会返回再次调用(这是切换到优化代码的最佳时间)。系统稍等片刻,等待它发生,当它没有发生时,run
最终会被“堆栈上替换”。这是一种典型的模式,在小型测试和基准测试中经常出现,而在实际代码中很少出现。
这难道不只是表明执行 100000 次函数调用比两个简单算术运算的 1000 次迭代成本更高——这是有道理的吗?
不,它没有显示;这只是人们被这个微基准误导的一种特殊方式。
就我个人而言,看到(使用 --print-opt-code
)编译器没有意识到 i *= 10; i /= 10;
是一个空操作并且可以完全删除,我有点失望。这将是另一个在这里被误导的好方法。哦,好吧,这可能是有原因的,为什么编译器比它看起来更难弄清楚该转换既适用又安全...
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。