scipy.fftpack的内存使用情况

时间:2017-03-07 17:38:37

标签: python numpy memory scipy fft

我在使用scipy的fftpack执行ffts时遇到高内存使用问题。使用模块memory_profiler获得的示例:

Line #    Mem usage    Increment   Line Contents
================================================
 4   50.555 MiB    0.000 MiB   @profile
 5                             def test():
 6  127.012 MiB   76.457 MiB       a = np.random.random(int(1e7))
 7  432.840 MiB  305.828 MiB       b = fftpack.fft(a)
 8  891.512 MiB  458.672 MiB       c = fftpack.ifft(b)
 9  585.742 MiB -305.770 MiB       del b, c
10  738.629 MiB  152.887 MiB       b = fftpack.fft(a)
11  891.512 MiB  152.883 MiB       c = fftpack.ifft(b)
12  509.293 MiB -382.219 MiB       del a, b, c
13  547.520 MiB   38.227 MiB       a = np.random.random(int(5e6))
14  700.410 MiB  152.891 MiB       b = fftpack.fft(a)
15  929.738 MiB  229.328 MiB       c = fftpack.ifft(b)
16  738.625 MiB -191.113 MiB       del a, b, c
17  784.492 MiB   45.867 MiB       a = np.random.random(int(6e6))
18  967.961 MiB  183.469 MiB       b = fftpack.fft(a)
19 1243.160 MiB  275.199 MiB       c = fftpack.ifft(b)

我试图理解这里发生了什么:

  1. 第7行和第8行的fft和ifft分配的内存量超过了返回结果所需的内存量。对于呼叫b = fftpack.fft(a),分配305 MiB。 b数组所需的内存量为16 B/value * 1e7 values = 160 MiB(代码返回complex128时每个值16 B)。似乎fftpack正在分配某种类型的工作空间,并且工作空间的大小与输出数组(?)相同。

  2. 在第10行和第11行再次运行相同的过程,但此时内存使用量较少,并且更符合我的预期。因此,似乎fftpack能够重用工作空间。

  3. 在第13-15行和第17-19行中,执行具有不同较小输入尺寸的ffts。在这两种情况下,都会分配比所需内存更多的内存,并且内存似乎不会被重用。

  4. 上面报告的内存使用情况与Windows任务管理器报告的内容一致(我能够读取这些图表的准确性)。如果我用更大的输入大小编写这样的脚本,我可以使我的(windows)计算机非常慢,表明它正在交换。

    第二个例子来说明为工作区分配的内存问题:

    factor = 4.5
    a = np.random.random(int(factor * 3e7))
    start = time()
    b = fftpack.fft(a)
    c = fftpack.ifft(b)
    end = time()
    print("Elapsed: {:.4g}".format(end - start))
    del a, b, c
    print("Finished first fft")
    
    a = np.random.random(int(factor * 2e7))
    start = time()
    b = fftpack.fft(a)
    c = fftpack.ifft(b)
    end = time()
    print("Elapsed: {:.4g}".format(end - start))
    del a, b, c
    print("Finished first fft")
    

    代码打印以下内容:

    Elapsed: 17.62
    Finished first fft
    Elapsed: 38.41
    Finished first fft
    Filename: ffttest.py
    

    注意具有较小输入大小的第二个fft如何计算需要两倍多的。我注意到在执行这个脚本时我的计算机速度非常慢(可能是交换)。

    问题:

    • fft是否可以在现场计算,而不需要额外的工作空间?如果是这样,为什么fftpack不这样做呢?

    • 这里的fftpack有问题吗?即使它需要额外的工作空间,为什么当fft以不同的输入大小重新运行时它不会重复使用它的工作空间?

    编辑:

1 个答案:

答案 0 :(得分:1)

这是一个已知问题,是由fftpack缓存其计算给定大小的fft的策略引起的。该缓存大约与计算输出一样大,因此如果一个缓存具有不同的输入大小的内存,则内存消耗会变得很大。

这里详细描述了这个问题:

https://github.com/scipy/scipy/issues/5986

Numpy也遇到了类似的问题:

https://github.com/numpy/numpy/pull/7686