如何在使用numpy向量化时避免巨大的额外内存消耗?

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

输出到控制台(注意,即使是第一次测试也需要大约8分钟的时间)显示512x512x512x16位阵列分配的消耗不超过预期(每个256MByte),并且看起来“最高”如预期的那样600MByte。

但是 ,在调用该函数的矢量化版本时,该过程将扩展到巨大的大小(超过7GB!)。 即使是最明显的解释,我可以想到解决这个问题 - 矢量化将输入和输出转换为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)。


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

当数组的dtype是对象时它将使用许多内存。

使用python函数做元素明智的计算是很慢的,甚至是由frompyfunc()转换为ufunc。


矢量化的一个基本问题是所有的中间值都是矢量。 虽然这是一个方便的方法来获得体面的速度提升,但内存使用率可能非常低,并且会不断颠簸您的CPU缓存。 为了克服这个问题,你需要使用一种以编译速度运行的显式循环,而不是以python的速度运行。 最好的方法是使用cython,用f2py或numexpr包装fortran代码。 你可以在这里找到这些方法的比较,尽管这更多地关注速度而不是内存使用。

链接地址: http://www.djcxy.com/p/9029.html

上一篇: How to avoid enormous additional memory consumption when using numpy vectorize?

下一篇: boost::interprocess memory allocator on anonymous segment