微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么“自我时间”在一个有效的空函数中如此之高?

如何解决为什么“自我时间”在一个有效的空函数中如此之高?

我有一个计算量很大的函数,它在循环中被多次调用

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 分析这个脚本时,我得到了这个:

enter image description here

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

我希望 func 拥有大部分自我时间,因为它是一个函数

这是为什么?

解决方法

(此处为 V8 开发人员。)

该函数在变得“热”一段时间后自动内联。

正确。 run 一经优化,优化器就决定将 func 内联到其中。之后,就profiler而言,所有的时间都花在了run上。
(要验证这一点,请使用 d8node--trace-turbo-inlining 中运行代码段。)
旁注:在这种情况下,获得 run 的优化代码需要比平时更长的时间,因为该函数永远不会返回再次调用(这是切换到优化代码的最佳时间)。系统稍等片刻,等待它发生,当它没有发生时,run 最终会被“堆栈上替换”。这是一种典型的模式,在小型测试和基准测试中经常出现,而在实际代码中很少出现。

这难道不只是表明执行 100000 次函数调用比两个简单算术运算的 1000 次迭代成本更高——这是有道理的吗?

不,它没有显示;这只是人们被这个微基准误导的一种特殊方式。

就我个人而言,看到(使用 --print-opt-code)编译器没有意识到 i *= 10; i /= 10; 是一个空操作并且可以完全删除,我有点失望。这将是另一个在这里被误导的好方法。哦,好吧,这可能是有原因的,为什么编译器比它看起来更难弄清楚该转换既适用又安全...

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。