在计算机中,没有任何数据类型是固定的,完全取决于如何看待这片数据的内存区域。
在numpy.ndarray.view中,提供对内存区域不同的切割方式,来完成数据类型的转换,而无须要对数据进行额外的copy,可以节约内存空间,我们可以将view看做对内存的展示方式。
如:
import numpy as np
x = np.arange(10, dtype=np.int)print('An integer array:', x)
print ('An float array:', x.view(np.float))

An integer array: [0 1 2 3 4 5 6 7 8 9]

An float array: [  0.00000000e+000   4.94065646e-324   9.88131292e-324   1.48219694e-323   1.97626258e-323   2.47032823e-323   2.96439388e-323   3.45845952e-3233.95252517e-323   4.44659081e-323]

在实际使用中我们往往会采取更复杂的dtype(也就是说view可以与dtype搭配使用)输出内存中的值,后面我们会示范对于结构化数组的较为复杂的view使用。

一、view和copy

我们从numpy.reshape()函数入手,文档对于其返回值的解释:

Returns
    -------
    reshaped_array : ndarray
        This will be a new view object if possible; otherwise, it will
        be a copy.  Note there is no guarantee of the *memory layout* (C- or
        Fortran- contiguous) of the returned array.

其返回值可能是一个view,或是一个copy。相应的条件为:
1、返回一个view条件:数据区域连续的时候
2、反之,则返回一个copy
我们得到了一个新概念,数组内存区域是否连续,numpy数组有flags['C_CONTIGUOUS']表示是否连续,有np.may_share_memory方法判断两个数组内存区域是否一致:

a = np.zeros([2,10], dtype=np.int32)
b = a.T  # 转置破坏连续结构a.flags['C_CONTIGUOUS']  # True
b.flags['C_CONTIGUOUS']  # Falsenp.may_share_memory(a,b)  # True
b.base is a  # True
id(b)==id(a)  # Falsea.shape = 20  # a的shape变了
a.flags['C_CONTIGUOUS']  # True# b.shape = 20
# AttributeError: incompatible shape for a non-contiguous array
# 想要使用指定shape的方式,只能是连续数组,但是reshape方法由于不改变原数组,所以reshape不受影响

数组切片是否会copy数据?

不过,数组的切片对象虽然并非contiguous,但是对它的reshape操作并不会copy新的对象,

a = np.arange(16).reshape(4,4)  print(a.T.flags['C_CONTIGUOUS'],a[:,0].flags['C_CONTIGUOUS'])
# False Falseprint (np.may_share_memory(a,a.T.reshape(16)),np.may_share_memory(a,a[:,0].reshape(4)))
# False True

但是,下一小节会介绍,高级切片会copy数组,开辟新的内存。

二、numpy的结构数组

利用np.dtype可以构建结构数组,numpy.ndarray.base会返回内存主人的信息,文档如下,

Help on getset descriptor numpy.ndarray.base:

base
    Base object if memory is from some other object.
    
    Examples
    --------
    The base of an array that owns its memory is None:
    
    >>> x = np.array([1,2,3,4])
    >>> x.base is None
    True
    
    Slicing creates a view, whose memory is shared with x:
    
    >>> y = x[2:]
    >>> y.base is x
    True

1、建立结构数组

persontype = np.dtype({'names':['name','age','weight','height'],'formats':['S30','i','f','f']}, align=True)
a = np.array([('Zhang',32,72.5,167),('Wang',24,65,170)],dtype=persontype)
a['age'].base

array([(b'Zhang', 32, 72.5, 167.),

(b'Wang', 24, 65. , 170.)],

dtype={'names':['name','age','weight','height'],

'formats':['S30','<i4','<f4','<f4'],

'offsets':[0,32,36,40],

'itemsize':44,

'aligned':True})

2、高级切片和普通切片的不同

In [26]: a.base
In [27]: a[0].base
In [28]: a[:1].base
Out[28]: array([123,   4,   5,   6,  78])
In [29]: a[[0,1]].baseIn [30]: a.base is None
Out[30]: True
In [31]: a[0].base is None
Out[31]: True
In [32]: a[:1].base is None
Out[32]: False
In [33]: a[[0,1]].base is None
Out[33]: True

由上可见高级切片会开辟新的内存,复制被切出的数据,这是因为这种不规则的内存访问使用原来的内存结构效率很低(逻辑相邻元素内存不相邻,标准的访问由于固定了起始和步长相当于访问相邻元素,所以效率较高),拷贝出来就是连续的内存数组了。

3、高级切片且不开辟新内存的方法

回到上上小节的结构数组,

print(a['age'].base is a)
print(a[['age', 'height']].base is None)

True

True

我们通过指定内存解析方式,实现不开辟新内存,将原内存解析为高级切片指定的结构数组,

def fields_view(arr, fields):dtype2 = np.dtype({name:arr.dtype.fields[name] for name in fields})# print(dtype2)# {'names':['age','weight'], 'formats':['<i4','<f4'], 'offsets':[32,36], 'itemsize':40}# print([(name,arr.dtype.fields[name]) for name in fields])# [('age', (dtype('int32'), 32)), ('weight', (dtype('float32'), 36))]# print(arr.strides)# (44,)return np.ndarray(arr.shape, dtype2, arr, 0, arr.strides)
'''
ndarray(shape, dtype=float, buffer=None, offset=0,|          strides=None, order=None)参数   类型  作用
shape   int型tuple   多维数组的形状
dtype   data-type   数组中元素的类型
buffer      用于初始化数组的buffer
offset  int     buffer中用于初始化数组的首个数据的偏移
strides     int型tuple   每个轴的下标增加1时,数据指针在内存中增加的字节数
order   'C' 或者 'F'  'C':行优先;'F':列优先
'''v = fields_view(a, ['age', 'weight'])
print(v.base is a)v['age'] += 10
print('+++'*10)
print(v)
print(v.dtype)
print(v.dtype.fields)
print('+++'*10)
print(a)
print(a.dtype)
print(a.dtype.fields)

True
++++++++++++++++++++++++++++++
[(42,  72.5) (34,  65. )]
{'names':['age','weight'], 'formats':['<i4','<f4'], 'offsets':[32,36], 'itemsize':40}
{'age': (dtype('int32'), 32), 'weight': (dtype('float32'), 36)}
++++++++++++++++++++++++++++++
[(b'Zhang', 42,  72.5,  167.) (b'Wang', 34,  65. ,  170.)]
{'names':['name','age','weight','height'], 'formats':['S30','<i4','<f4','<f4'], 'offsets':[0,32,36,40], 'itemsize':44, 'aligned':True}
{'name': (dtype('S30'), 0), 'age': (dtype('int32'), 32), 'weight': (dtype('float32'), 36), 'height': (dtype('float32'), 40)}

这里注意一下.dtype的’itemsize‘参数,表示添加一条(行)数据,内存增加了多少字节,由于保存了'offsets'偏移信息,我们生成的dtype展示的是一个稀疏的结构,但是每一行不会有多余的尾巴,这是因为空元素是由实元素记录偏移量的空隙产生的。

在『Numpy』内存分析_numpy.dtype解析内存数据中我们会更详细的介绍有关数组内存解析的方法。

转载于:https://www.cnblogs.com/hellcat/p/8715830.html

『Numpy』内存分析_高级切片和内存数据解析相关推荐

  1. 『Numpy』常用方法记录

    numpy教程 防止输出省略号 import numpy as np np.set_printoptions(threshold=np.inf) 广播机制 numpy计算函数返回默认是一维行向量: i ...

  2. 『TensorFlow』分布式训练_其二_单机多GPU并行GPU模式设定

    建议比对『MXNet』第七弹_多GPU并行程序设计 一.tensorflow GPU设置 GPU指定占用 gpu_options = tf.GPUOptions(per_process_gpu_mem ...

  3. 转录组分析_高级转录组分析和R数据可视化

    封面来源:https://www.zhihu.com/question/304747766 常规转录组是我们最常接触到的一种高通量测序数据类型,其实验方法成熟,花费较低,是大部分CNS必备的技术,以后 ...

  4. java怎么看内存值_【java】内存分析

    在J2SE中,通过进行内存分析,可以让我们更好的理解我们的程序在内存中是怎么被分配内存的.也能让我们更好的理解我们的代码是怎么运行的. 对于我自己来说分析内存也是一件很有趣的事情.所以下面通过一个例子 ...

  5. 『数据库』朴实无华且枯燥的数据库文章--关系数据理论

    『数据库』 朴实无华且枯燥的数据库教程–入门必看!(不收藏,真的吃亏了) 文章目录 问题的提出 规范化 数据依赖的公理系统 模式的分解 小结 问题的提出 一.概念回顾 关系:描述实体.属性.实体间的联 ...

  6. 全面理解java内存模型_深入理解Java内存模型(八)——总结

    处理器内存模型 顺序一致性内存模型是一个理论参考模型,JVM和处理器内存模型在设计时通常会把顺序一致性内存模型作为参照.JVM和处理器内存模型在设计时会对顺序一致性模型做一些放松,因为如果完全按照顺序 ...

  7. java设置native内存大小_如何定位native内存泄露问题?

    运行一段时间后,程序出现异常:部分操作无法进行.异常日志如下: java.lang.OutOfMemoryError: unable to create new native thread at ja ...

  8. linux内存管理_浅谈Linux内存管理

    1. 扫盲篇 1.1 操作系统存储层次 常见的计算机存储层次如下: 寄存器:CPU提供的,读写ns级别,容量字节级别. CPU缓存:CPU和CPU间的缓存,读写10ns级别,容量较大一些,百到千节. ...

  9. unity如何检测内存泄漏_如何排查Java内存泄漏?看懂这一篇就够用了

    原文:https://www.toptal.com/java/hunting-memory-leaks-in-java 作者:Jose Ferreirade Souza Filho 译者:Emma来源 ...

最新文章

  1. 鸿蒙系统突破,华为解锁新成就!新系统用户突破1亿,鸿蒙系统也传来了新消息...
  2. 使用管道符在PowerShell中进行各种数据操作
  3. CF750F. New Year and Finding Roots
  4. 关于table的中元素对齐方式的注意点
  5. poj 2502 Subway md自闭了,之后再看吧f**k
  6. 设计模式之美:Bridge(桥接)
  7. java类注释_Java注释,java类注释详解
  8. MATLAB 中gcf、gca 以及gco三者的解析
  9. 20155322 2016-2017-2 《Java程序设计》第7周学习总结
  10. Lua游戏客户端框架通用功能模块
  11. JPS(Jump Point Search)寻路及实现代码分析
  12. java中是什么意思_java中@什么意思
  13. 怎么制作区域分布图,怎么做网点分布图
  14. ​【​观察】云栖大会共话JDM模式 揭秘创新背后的价值和启示
  15. Windows系统 gpedit命令详解,Windows系统使用命令行查看组策略
  16. cad计算机在哪,Win7系统中cad临时文件保存在哪里
  17. 大学必考计算机软件cad,大学CAD考试试题单选多选作图操作题.doc
  18. OpenGL的图形渲染过程
  19. 第十二届蓝桥杯--第二场--B-双阶乘
  20. 阿里如何定义团队的研发效能? 1

热门文章

  1. esxi远程管理端口_如何在 vmware esxi 中开放 VNC功能及端口实现远程管理 完整篇...
  2. 生物信息学搞计算机,生物信息学前景展望,谈谈感想(已经停止)
  3. k-gram 拼写校正 java_拼写纠错-基于lucene-ngram实现拼写纠错
  4. 数组的最长平台c语言,2010台湾省C语言版高级
  5. 【Mybatis】resultMap继承
  6. ECMAScript标准资料
  7. 【Error】Provider com.sun.xml.stream.ZephyrParserFactory not found
  8. 为什么jsp写script代码报错_JSP 报错:ReferenceError: $ is not defined
  9. linux 页面内容输出,Node.js 一个简单的页面输出
  10. php获取当前设备,Linux_在Linux系统中使用lsblk和blkid显示设备信息的方法,今天我们将会向你展示如何使 - phpStudy...