如何在使用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