【问题标题】:Why is my moving average algorithm so slow?为什么我的移动平均算法这么慢?
【发布时间】:2020-01-19 05:05:17
【问题描述】:

我编写了一个 Fortran 函数,它以非常简单的方式计算一维数字数组的移动平均值:

function moving_average(data, w)

    implicit none

    integer, intent(in) :: w
    real(8), intent(in) :: data(:)

    integer :: n, i
    real(8) :: moving_average(size(data)-w+1)

    n = w-1

    do i=1, size(data)-n
        moving_average(i) = mean(data(i:i+n))
    end do

end function

其中函数mean定义为:

real(8) function mean(data)

    implicit none

    real(8), dimension(:), intent(in) :: data

    mean = sum(data)/size(data)

end function

在我的笔记本电脑上运行 moving_average 函数时,数据集为 100000 个数字,窗口宽度为 1000,需要 0.1 秒。但是,this post 中的函数 running_mean 使用 numpy 只需要 1 毫秒。为什么我的算法这么慢?

【问题讨论】:

  • real(8) 丑陋且不便携
  • @VladimirF 你有什么建议呢?使用selected_real_kind?
  • 一个命名常量。如果它必须等于 8,那就这样吧,但 selected_real_kind 更好。 stackoverflow.com/questions/838310/fortran-90-kind-parameter
  • 或尝试iso_fortran_env,例如use iso_fortran_env, only: real64; real(real64) :: data(:)。 Fortran标准的iso_fortran_env中至少定义了以下类型:int8int16int32int64real32real64real128

标签: optimization fortran moving-average


【解决方案1】:

您的算法的顺序为 O(n*m),其中 n 是移动平均线的大小,m 是数组的大小。

每次在数组moving_average 中计算一个点时,都执行以下步骤:

  • 提取数组的一部分
  • 计算该切片的总和
  • 除以常数n

但是,moving_average(i)moving_average(i+1) 的关联方式如下:

moving_average(i+i) = moving_average(i) + (data(i+n) - data(i-1))/n

当你使用这个时,你可以将计算时间从 O(n*m) 减少到 O(m)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-25
    • 2020-07-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多