优化numpy中的内存使用

2024-06-25 06:13:26 发布

您现在位置:Python中文网/ 问答频道 /正文

下面的程序使用PyGame加载两个图像,将它们转换为Numpy数组,然后执行其他一些Numpy操作(例如FFT)以发出最终结果(几个数字)。输入可以很大,但在任何时候都只能有一个或两个大对象处于活动状态。在

一个测试图像大约是10万像素,一旦被灰度化,它就转换成10MB。它被转换成一个Numpy数组uint8,经过一些处理(应用Hamming windows),它是一个dtype float64的数组。两个图像以这种方式加载到数组中;后面的FFT步骤将得到一个dtype complex128的数组。在添加过多的gc.collect调用之前,程序内存大小往往会随着每一步的增加而增加。此外,似乎大多数Numpy操作都会产生最高精度的结果。在

在我的1GB Linux机器上运行测试(没有gc.collect调用)会导致长时间的震荡,这是我没有等待的。我还没有详细的内存使用统计信息——我尝试了一些Python模块和time命令,但是没有用;现在我要研究valgrind。观察PS(并处理测试后期的机器无响应)表明最大内存使用量约为800MB。在

一个1000万个complex128单元阵列应该占用160MB。在同一时间(理想情况下)最多只能有两个这样的库,再加上并非虚无缥缈的Python和Numpy库以及其他工具,可能意味着可以使用500MB。在

我可以从两个角度来解决这个问题:

  • 尽快丢弃中间数组。这就是gc.collect调用的目的——它们似乎已经改善了这种情况,因为它现在只需要几分钟的震荡就完成了;-)。我认为可以预期,像Python这样的语言中的内存密集型编程将需要一些手动干预。

  • 在每一步都使用不太精确的Numpy数组。不幸的是,返回数组的操作,如fft2,似乎不允许指定类型。

所以我的主要问题是:在Numpy数组操作中有没有指定输出精度的方法?

更一般地说,在使用Numpy时是否还有其他常用的内存保存技术?在

另外,Numpy是否有一种更惯用的释放数组内存的方法?(我想这会使数组对象保持在Python中,但处于不可用的状态。)显式删除然后立即GC会让人觉得很麻烦。在

import sys
import numpy
import pygame
import gc


def get_image_data(filename):
    im = pygame.image.load(filename)
    im2 = im.convert(8)
    a = pygame.surfarray.array2d(im2)
    hw1 = numpy.hamming(a.shape[0])
    hw2 = numpy.hamming(a.shape[1])
    a = a.transpose()
    a = a*hw1
    a = a.transpose()
    a = a*hw2
    return a


def check():
    gc.collect()
    print 'check'


def main(args):
    pygame.init()

    pygame.sndarray.use_arraytype('numpy')

    filename1 = args[1]
    filename2 = args[2]
    im1 = get_image_data(filename1)
    im2 = get_image_data(filename2)
    check()
    out1 = numpy.fft.fft2(im1)
    del im1
    check()
    out2 = numpy.fft.fft2(im2)
    del im2
    check()
    out3 = out1.conjugate() * out2
    del out1, out2
    check()
    correl = numpy.fft.ifft2(out3)
    del out3
    check()
    maxs = correl.argmax()
    maxpt = maxs % correl.shape[0], maxs / correl.shape[0]
    print correl[maxpt], maxpt, (correl.shape[0] - maxpt[0], correl.shape[1] - maxpt[1])


if __name__ == '__main__':
    args = sys.argv
    exit(main(args))

Tags: 内存imageimportnumpycheckargs数组pygame
2条回答

如果我没弄错的话,你在计算两幅图像之间的卷积。Scipy包包含一个专用的模块(ndimage),这可能比通过傅立叶变换的“手动”方法更节省内存。最好试着用它而不是去做裸体游戏。在

This 上面说“SCIPY0.8将对几乎所有的fft代码提供单精度支持”, scipy0.8.0beta1刚刚发布。
(没试过,胆小鬼)

相关问题 更多 >