使用numpy vectorize时如何避免大量额外的内存消耗?

时间:2011-08-16 12:43:38

标签: python memory numpy vectorization

以下代码最能说明我的问题:

到控制台的输出(NB甚至第一次测试需要大约8分钟)显示512x512x512x16位阵列分配消耗不超过预期(每个256MByte),并且通常查看“顶部”过程仍然低于预期的600MByte。

然而,在调用函数的矢量化版本时,该过程会扩展为巨大大小(超过7GByte!)。即便是我能想到的最明显的解释 - 向量化将输入和输出转换为内部的float64 - 即使向量化函数返回一个int16,也只能占用几千兆字节,返回的数组肯定是一个int16。有没有办法避免这种情况发生?我使用/理解vectorize的otypes参数是错误的吗?

import numpy as np
import subprocess

def logmem():
    subprocess.call('cat /proc/meminfo | grep MemFree',shell=True)

def fn(x):
    return np.int16(x*x)

def test_plain(v):
    print "Explicit looping:"
    logmem()
    r=np.zeros(v.shape,dtype=np.int16)
    for z in xrange(v.shape[0]):
        for y in xrange(v.shape[1]):
            for x in xrange(v.shape[2]):
                r[z,y,x]=fn(x)
    print type(r[0,0,0])
    logmem()
    return r

vecfn=np.vectorize(fn,otypes=[np.int16])

def test_vectorize(v):
    print "Vectorize:"
    logmem()
    r=vecfn(v)
    print type(r[0,0,0])
    logmem()
    return r

logmem()    
s=(512,512,512)
v=np.ones(s,dtype=np.int16)
logmem()
test_plain(v)
test_vectorize(v)
v=None
logmem()

我正在使用amd64 Debian Squeeze系统上最新的Python / numpy版本(Python 2.6.6,numpy 1.4.1)。

2 个答案:

答案 0 :(得分:3)

矢量化的基本问题是所有中间值也是矢量。虽然这是获得不错的速度增强的便捷方式,但它在内存使用方面效率非常低,而且会不断地颠覆CPU缓存。要解决这个问题,您需要使用一种方法,该方法具有以编译速度运行的显式循环,而不是以python速度运行。最好的方法是使用cython,包含f2pynumexpr的fortran代码。您可以找到这些方法的比较here,尽管这更多地关注速度而非内存使用。

答案 1 :(得分:2)

你可以阅读vectorize()的源代码。它将数组的dtype转换为object,并调用np.frompyfunc()从python函数创建ufunc,ufunc返回对象数组,最后vectorize()将对象数组转换为int16数组。

当数组的dtype是object时,它会使用很多内存。

使用python函数进行元素计算很慢,甚至可以通过frompyfunc()转换为ufunc。