【问题标题】:Why masked arrays seems to be smaller compared to unmasked array?为什么与未屏蔽数组相比,屏蔽数组似乎更小?
【发布时间】:2020-02-28 17:02:31
【问题描述】:

我试图了解 numpy 掩码数组和带有 nans 的普通数组之间的大小差异。

import numpy as np
g = np.random.random((5000,5000))
indx = np.random.randint(0,4999,(500,2))
mask =  np.full((5000,5000),False,dtype=bool)
mask[indx] = True
g_mask = np.ma.array(g,mask=mask)

我使用以下answer 来计算对象的大小:

import sys
from types import ModuleType, FunctionType
from gc import get_referents
​
# Custom objects know their class.
# Function objects seem to know way too much, including modules.
# Exclude modules as well.
BLACKLIST = type, ModuleType, FunctionType
​
​
def getsize(obj):
    """sum size of object & members."""
    if isinstance(obj, BLACKLIST):
        raise TypeError('getsize() does not take argument of type: '+ str(type(obj)))
    seen_ids = set()
    size = 0
    objects = [obj]
    while objects:
        need_referents = []
        for obj in objects:
            if not isinstance(obj, BLACKLIST) and id(obj) not in seen_ids:
                seen_ids.add(id(obj))
                size += sys.getsizeof(obj)
                need_referents.append(obj)
        objects = get_referents(*need_referents)
    return size

这给了我以下结果:

getsize(g)
>>>200000112
getsize(g_mask)
>>>25000924

为什么未屏蔽数组比屏蔽数组大?如何估计掩码数组与未掩码数组的实际大小?

【问题讨论】:

    标签: python arrays numpy size mask


    【解决方案1】:
    In [23]: g = np.random.random((5000,5000)) 
        ...: indx = np.random.randint(0,4999,(500,2)) 
        ...: mask =  np.full((5000,5000),False,dtype=bool) 
        ...: mask[indx] = True 
        ...: g_mask = np.ma.array(g,mask=mask)    
    

    比较g数组和g_mask_data属性,我们发现后者只是前者的view

    In [24]: g.__array_interface__                                                  
    Out[24]: 
    {'data': (139821997776912, False),
     'strides': None,
     'descr': [('', '<f8')],
     'typestr': '<f8',
     'shape': (5000, 5000),
     'version': 3}
    In [25]: g_mask._data.__array_interface__                                       
    Out[25]: 
    {'data': (139821997776912, False),
     'strides': None,
     'descr': [('', '<f8')],
     'typestr': '<f8',
     'shape': (5000, 5000),
     'version': 3}
    

    它们的数据缓冲区相同,但它们的id 不同:

    In [26]: id(g)                                                                  
    Out[26]: 139822758212672
    In [27]: id(g_mask._data)                                                       
    Out[27]: 139822386925440
    

    面具也一样:

    In [28]: mask.__array_interface__                                               
    Out[28]: 
    {'data': (139822298669072, False),
     'strides': None,
     'descr': [('', '|b1')],
     'typestr': '|b1',
     'shape': (5000, 5000),
     'version': 3}
    In [29]: g_mask._mask.__array_interface__                                       
    Out[29]: 
    {'data': (139822298669072, False),
     'strides': None,
     'descr': [('', '|b1')],
     'typestr': '|b1',
     'shape': (5000, 5000),
     'version': 3}
    

    其实用这个构造,_mask就是同一个数组:

    In [30]: id(mask)                                                               
    Out[30]: 139822385963056
    In [31]: id(g_mask._mask)                                                       
    Out[31]: 139822385963056
    

    掩码数组的__array_interface__._data属性的数组:

    In [32]: g_mask.__array_interface__                                             
    Out[32]: 
    {'data': (139821997776912, False),
    

    nbytes 是数组的数据缓冲区大小:

    In [34]: g_mask.data.nbytes                                                     
    Out[34]: 200000000
    In [35]: g_mask.mask.nbytes                                                     
    Out[35]: 25000000
    

    一个布尔数组每个元素有 1 个字节,一个 float64,有 8 个字节。

    【讨论】:

    • 感谢您知道如何正确估计尺寸?
    • 我的描述中缺少什么? nbytes?屏蔽增加了mask 的大小。
    • 是的,我不明白如何获得两个不同对象的字节大小。我想了解的是,与未屏蔽数组相比,屏蔽数组是否消耗更多内存。
    • 我试图解释。掩码数组实际上是 2 个数组 - 将两者的大小相加。你了解 numpy 数组是如何存储的吗?以及copyview 之间的区别?
    • 是的,我知道视图是什么,我只是不知道使用 data.nbytes 可以拥有字节。 g_mask.mask.nbytes 正是掩码的字节值的数量我想知道掩码类是否还使用了其他一些字节。
    【解决方案2】:

    numpy.ndarray 没有tp_traverse,因此它与您尝试使用的getsize 函数不兼容。 GC 系统看不到掩码数组的 ndarray 部分所拥有的引用。特别是,g_maskbase 没有包含在您的输出中。

    【讨论】:

    • 谢谢,知道如何获取两个对象的大小以进行比较吗?
    猜你喜欢
    • 1970-01-01
    • 2023-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-22
    • 2018-01-25
    相关资源
    最近更新 更多