「Python数据科学」ndarray对象的内部机理与数据存储顺序

引言

前面的内容中简单介绍了多维数组ndarry的创建、基本属性以及索引、切片的常用操作。但是,要真正更好地理解各项操作的使用及预期操作的结果时,还是需要对ndarray的内部机理及所谓的数据存储顺序有一定的了解,才能将ndarry应用得更加得心应手。

本文的主要内容有:

1、ndarray对象的内部机理

2、ndarray的数据存储顺序

ndarray对象的内部机理

NumPy中的多维数组结构ndarray之所以快,是因为ndarray提供了一种将同构类型的数据块(可以是连续的或者步进式的)解释为多维数组对象的方式。数据类型(dtype)决定了数据的解释方式,比如浮点型、整型、布尔型等。

我们对ndarray的一些操作,比如切片,实质上只是创建了一个针对原始数据存储的新的视图,更确切说,是创建了一种原始数据的元数据,从而产生对原始数据的新的解释方式。

文字内容比较抽象,首先通过一个图像来粗糙解释ndarray对象的内部结构:

f776e3a1de5f5a27ee90f4f741b2f2e7.jpeg

从上图中可以看出,ndarray对象主要有两个部分组成:

1、原始数组数据,也就是数据缓冲区,可以理解成为C数组或者Fortran数组,是一个连续且固定的内存块,连续存储真实的数组元素。

2、元数据,有关原始数组数据的各种信息,用于描述如何解释数据缓冲区中的数据。

正是由于元数据和原始数组数据分别存储结构,可以支撑后续零拷贝的数组视图的实现。也就是说,当我们对原始数组进行切片时,实际上是创建了一个新的元数据信息,增加了一种对原始数组的数据的新的解释方式,而实际上还是共用同一份原始数组数据。

可以通过代码来验证上述内容,首先先看一个ndarray的内部结构信息:

396ae3b50253334bfbc6fc278269d407.jpeg

简单说明一下:

1、ctypes.data属性:存储了原始数组的指针

2、dtype属性:数组元素的类型

3、itemsize属性:数组元素占用的字节数

4、shape属性:数组的形状

5、strides属性:步进信息

其中,strides属性需要特别说明一下,所谓步进信息,也就是一个步长的数组,记录了在各个维度上,前进到下一个元素所需要移动的字节数。

接下来,我们创建数组的切片,同时验证是否创建新的元数据,以及是否指向了原始数组:

5d96ca9023844803ba531f31fb1353c8.jpeg

结合上面的代码执行结果,简单说明一下NumPy中ndarray的所谓“0拷贝”机制。

1、所谓0拷贝,实际上还是会创建一个Python对象,0拷贝描述的是不创建新的原始数组,ctypes.data指针指向的是原始数组中切片中的首个元素的位置。

2、切片对象存储的步进信息strides是真正用于解释切片中可见数据元素的元信息。

ndarray的数据存储顺序

了解了ndarray对象的内部机理,接下来再来对原始数据的存储顺序进行展开说明。

关于数据的存储,其实主要有两种存储风格:

1、C风格:也就是C语言中,数组数据的存储顺序,也叫作Row-Major(行优先、按行存储)的数据存储顺序。

2、Fortran风格:也就是Fortran语言中,数组数据的存储顺序,也叫作Column-Major(列优先、按列存储)的数据存储顺序。

首先,通过代码来看下这两种存储顺序(更确切的说是数据的访问顺序,因为底层存储是数组创建之初已经确定了)

e71f48725368a4f70a885069cbe394ec.jpeg

可以看到,如下图所示,对同一个数组创建两种顺序的解释视图后,对应的步进信息有明显的不同,索引元素的顺序确实发生了变化。

3f8cc720f6bb688c2f21e7f149e8dc37.jpeg

但是,我们需要知道,在“0拷贝”机制之下,原始数组的数据存储顺序是没有发生任何修改的。

同样通过代码来说明:

0007869a539762e546578aa898d3fe99.jpeg

简单说明一下上述代码:

1、首先获取到数组的数据类型,从而确认每个数组元素所占用的字节数。

2、通过ctypes类库将ndarray中指向原始数组的指针属性ctypes.data转换为一个对应数据类型的C指针。

3、通过C指针对原始数组进行元素的索引,从而确认存储顺序未发生变化。

总结

本文首先介绍了ndarray对象的内部机理,理解了其元数据和原始数组的构成,并引出了0拷贝视图机制的基础strides步进属性。最后介绍了关于数组数据存储顺序的两种方式,并通过C指针验证了不同视图下的原始数组存储顺序不变的特性。

以上就是本文的全部内容,感谢您的拨冗阅读!

df2f22f92a78980e35a8cd7406d53054.jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南宫理的日知录

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值