1. 程式人生 > >『Numpy』內存分析_利用共享內存創建數組

『Numpy』內存分析_利用共享內存創建數組

highlight block 標識 查看 空間 types length PE 獲取

引、內存探究常用函數

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, ‘\n‘, 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‘],‘\n‘,data[‘sin‘],‘\n‘,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的字段,見下篇。

『Numpy』內存分析_利用共享內存創建數組