• 『Numpy』内存分析_利用共享内存创建数组


    引、内存探究常用函数

    id(),查询对象标识,通常返回的是对象的地址

    sys.getsizeof(),返回的是 这个对象所占用的空间大小,对于数组来说,除了数组中每个值占用空间外,数组对象还会存储数组长度、数组类型等其他信息

    numpy.ndarray.ctypes.data属性,返回numpy数组的内存位置

    array.array.buffer_info(),数组对象的内存信息,返回元素起始地址和元素个数

    help(array.buffer_info)
    '''
    buffer_info(self, /)
        Return a tuple (address, length) giving the current memory address and the length in items of the buffer
        used to hold array's contents.
    '''

     numpy.ndarray.nbytes,获取数组中存储的值的占用空间大小

    numpy.ndarray.items,获取数组中每个值的占用空间大小

    部分函数试用如下,有意思的是对numpy数组中元素的迭代,它们的id是两个循环出现的地址,原因不明

    a = np.array([1,2,3,4,5])
    
     a.ctypes.data
    # 2199487215904
    
    id(a)
    # 2199565580288
    
    sys.getsizeof(a)
    # 116
    
    a.nbytes
    # 20
    
    a.itemsize
    # 4
    
    for i in a:
        print(id(i), type(i), i)
    # 2199565034888 <class 'numpy.int32'> 1
    # 2199565034912 <class 'numpy.int32'> 2
    # 2199565034888 <class 'numpy.int32'> 3
    # 2199565034912 <class 'numpy.int32'> 4
    # 2199565034888 <class 'numpy.int32'> 5
    

    一、使用array.array和numpy.frombuffer实现动态数组

    利用array.array数组对象的内存是确定连续的特性(这也是list为什么不行的原因,实际上array的buffer_info方法就可以查看内存占用情况,返回),使用np访问这块内存,并指定解析方式,从内存创建数组,

    从内存创建数组

    此时两个对象共用内存,修改数据会影响两者,

    import numpy as np
    from array import array
    
    a = array('d', [1,2,3,4])
    na = np.frombuffer(a, dtype=np.float)
    
    print(a, na)
    na[1] = 20
    print(a, na)
    

     array('d', [1.0, 2.0, 3.0, 4.0]) [ 1. 2. 3. 4.]

    array('d', [1.0, 20.0, 3.0, 4.0]) [ 1. 20. 3. 4.]

    多维数组创建以及动态添加元素演示

    多维就是一维np.array创建后reshape就行了,

    import math
    buf = array('d')
    for i in range(5):
        buf.append(math.sin(i*0.1))
        buf.append(math.cos(i*0.1))
    data = np.frombuffer(buf, dtype=np.float).reshape(-1,2)
    print(data)
    
    [[ 0.          1.        ]
     [ 0.09983342  0.99500417]
     [ 0.19866933  0.98006658]
     [ 0.29552021  0.95533649]
     [ 0.38941834  0.92106099]]

    array内存分配机制以及动态数组构建的注意项

    import sys
    
    a = array("d")
    for i in range(10):
        a.append(i)
        if i == 2:
            na = np.frombuffer(a, dtype=float)
        print(a.buffer_info(), sys.getsizeof(a))
        if i == 4:
            print()
    
    (140269607002576, 1) 96
    (140269607002576, 2) 96
    (140269607002576, 3) 96
    (140269607002576, 4) 96
    (140269607286768, 5) 128
    
    (140269607286768, 6) 128
    (140269607286768, 7) 128
    (140269607286768, 8) 128
    (140269607021360, 9) 192
    (140269607021360, 10) 192

    可以看到初始化后会初始化一段空间,当不够时会继续分配一段新的空间。

    numpy数组指针初始化于i=2时,所以并未更新到最新数据,可以看到数据解析的并非我们想要的,

    print(na.ctypes.data, '
    ', na)
    

     140269607002576

    [ 6.93023941e-310 1.01768729e-316 0.00000000e+000]

    二、利用struct结构体实现动态结构数组

    利用struct结构体接收行,利用bytearray存储二进制数据,利用frombuffer读取数据,其中使用需要注意数据解析格式的设定要符合struct接收格式设定

    import struct
    
    buf = bytearray()
    for i in range(5):
        buf += struct.pack('=hdd',i,math.sin(i*0.1),math.cos(i*0.1))  # ’=‘表示不进行数据内存占用对齐(整形和浮点型占用内存不同)
    dtype = np.dtype({'names':['id','sin','cos'],'formats':['h','d','d']},align=False)  # align表示是否数据已经进行了对齐
    data = np.frombuffer(buf,dtype=dtype)
    print(data)
    print(data['id'],'
    ',data['sin'],'
    ',data['cos'])
    
    [(0,  0.        ,  1.        )
    (1, 0.09983342, 0.99500417) (2, 0.19866933, 0.98006658)
    (3, 0.29552021, 0.95533649) (4, 0.38941834, 0.92106099)]
    [0 1 2 3 4] [ 0. 0.09983342 0.19866933 0.29552021 0.38941834] [ 1. 0.99500417 0.98006658 0.95533649 0.92106099]

    此时保存出来的数组类似表格,和pd的DataFrame格式类似,行索引是0~n,列索引既可以是0~m也可以使用names的字段,见下篇。

  • 相关阅读:
    文件路径总结
    git本地仓库关联远程仓库
    webpack-dev-server版本
    box-sizing重置
    事件委托优缺点和实现
    移动端经验总结(持续更新)
    点击其他区域关闭dialog
    css3图片变灰
    安装 ubuntu 后,使用 sed 更换国内源
    在virtualBox中打开vdi(转载)
  • 原文地址:https://www.cnblogs.com/hellcat/p/8709552.html
Copyright © 2020-2023  润新知