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

Python 使用numpy矢量化时如何避免巨大的额外内存消耗?,python,memory,numpy,vectorization,Python,Memory,Numpy,Vectorization,下面的代码最能说明我的问题: 控制台的输出(注意,即使是第一次测试,运行也需要8分钟)显示512x512x512x16位阵列分配的消耗量不超过预期(每个分配量为256MB),从“顶部”看,进程通常保持在预期的600MB以下 然而在调用该函数的矢量化版本时,该过程会扩展到巨大的规模(超过7GB!)。即使是我能想到的最明显的解释——矢量化是在内部将输入和输出转换为float64——也只能解释几GB,即使矢量化函数返回int16,返回的数组肯定是int16。有没有办法避免这种情况发生?我是否使用/理解

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

控制台的输出(注意,即使是第一次测试,运行也需要8分钟)显示512x512x512x16位阵列分配的消耗量不超过预期(每个分配量为256MB),从“顶部”看,进程通常保持在预期的600MB以下

然而在调用该函数的矢量化版本时,该过程会扩展到巨大的规模(超过7GB!)。即使是我能想到的最明显的解释——矢量化是在内部将输入和输出转换为float64——也只能解释几GB,即使矢量化函数返回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挤压系统(Python 2.6.6,numpy 1.4.1)上当前的Python/numpy版本。

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

当数组的数据类型为object时,它将使用大量内存


使用python函数进行元素计算的速度很慢,甚至frompyfunc()会将is转换为ufunc。

矢量化的一个基本问题是,所有中间值也都是矢量。虽然这是一种方便的速度提升方法,但它的内存使用效率非常低,并且会不断地破坏CPU缓存。为了克服这个问题,您需要使用一种方法,该方法使显式循环以编译速度而不是python速度运行。实现这一点的最佳方法是使用或包装的fortran代码。您可以找到这些方法的比较,尽管这更注重速度而不是内存使用。

您是否尝试过在其上运行cProfile?不,我从未尝试过分析python代码;我的印象是它只会告诉我打电话的时间。它还可以告诉我一些关于内存分配的有用信息吗?分析代码将告诉您占用的时间最多的是什么,这可能有助于您找出导致代码减速的原因。Heapy还将为您提供内存占用的准确结果。