为什么我的移动平均算法这么慢?
Why is my moving average algorithm so slow?
我编写了一个 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 个数字且 window 宽度为 1000 时,需要 0.1 秒。然而,this post中的函数running_mean
使用numpy
只需要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)
我编写了一个 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 个数字且 window 宽度为 1000 时,需要 0.1 秒。然而,this post中的函数running_mean
使用numpy
只需要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)