Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >从Numpy中的ascontiguousarray说起

从Numpy中的ascontiguousarray说起

作者头像
王云峰
发布于 2019-12-25 07:06:28
发布于 2019-12-25 07:06:28
1.4K00
代码可运行
举报
运行总次数:0
代码可运行

1. 概述

在使用Numpy的时候,有时候会遇到下面的错误:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
AttributeError: incompatible shape for a non-contiguous array

看报错的字面意思,好像是不连续数组的shape不兼容。

有的时候,在看别人代码时会时不时看到ascontiguous()这样的一个函数,查文档会发现函数说明只有一句话:“Return a contiguous array (ndim >= 1) in memory (C order).”

光靠这些信息,似乎没能道出Numpy里面contiguous array和non-contiguous array有什么区别,以及为什么需要进行ascontiguous操作?带着这些疑问,我搜了比较多的资料,在stack overflow上发现一个比较详细的回答,简单明白地将Numpy里面的数组的连续性问题解释清楚了,因此这里翻译过来,希望能帮助到别的有同样疑问的小伙伴。

2. 额外知识: C order vs Fortran order

所谓C order,指的是行优先的顺序(Row-major Order),即内存中同行的存在一起,而Fortran Order则指的是列优先的顺序(Column-major Order),即内存中同列的存在一起。这种命名方式是根据C语言和Fortran语言中数组在内存中的存储方式不同而来的。Pascal, C,C++,Python都是行优先存储的,而Fortran,MatLab是列优先存储的。

3. 译文

所谓contiguous array,指的是数组在内存中存放的地址也是连续的(注意内存地址实际是一维的),即访问数组中的下一个元素,直接移动到内存中的下一个地址就可以。

考虑一个2维数组arr = np.arange(12).reshape(3,4)。这个数组看起来结构是这样的:

在计算机的内存里,数组arr实际存储是像下图所示的:

这意味着arrC连续的C contiguous)的,因为在内存是行优先的,即某个元素在内存中的下一个位置存储的是它同行的下一个值。

如果想要向下移动一列,则只需要跳过3个块既可(例如,从0到4只需要跳过1,2和3)。

上述数组的转置arr.T则没有了C连续特性,因为同一行中的相邻元素现在并不是在内存中相邻存储的了:

这时候arr.T变成了Fortran 连续的Fortran contiguous),因为相邻列中的元素在内存中相邻存储的了。

从性能上来说,获取内存中相邻的地址比不相邻的地址速度要快很多(从RAM读取一个数值的时候可以连着一起读一块地址中的数值,并且可以保存在Cache中)。这意味着对连续数组的操作会快很多。

由于arr是C连续的,因此对其进行行操作比进行列操作速度要快,例如,通常来说

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
np.sum(arr, axis=1) # 按行求和

会比

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
np.sum(arr, axis=0) # 按列求和

稍微快些。

同理,在arr.T上,列操作比行操作会快些。

4. 补充

Numpy中,随机初始化的数组默认都是C连续的,经过不规则的slice操作,则会改变连续性,可能会变成既不是C连续,也不是Fortran连续的。

Numpy可以通过.flags熟悉查看一个数组是C连续还是Fortran连续的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> import numpy as np
>>> arr = np.arange(12).reshape(3, 4)
>>> arr.flags
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : False
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False

从输出可以看到数组arr是C连续的。

arr进行按列的slice操作,不改变每行的值,则还是C连续的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> arr
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> arr1 = arr[:3, :]
>>> arr1
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> arr1.flags
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : False
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False

如果进行在行上的slice,则会改变连续性,成为既不C连续,也不Fortran连续的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> arr1 = arr[:, 1:3]
>>> arr1.flags
  C_CONTIGUOUS : False
  F_CONTIGUOUS : False
  OWNDATA : False
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False

此时利用ascontiguousarray函数,可以将其变为连续的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> arr2 = np.ascontiguousarray(arr1)
>>> arr2.flags
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False

可以这样认为,ascontiguousarray函数将一个内存不连续存储的数组转换为内存连续存储的数组,使得运行速度更快。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-03-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
numpy 和 pytorch tensor 的内存连续性 contiguous
行是指多维数组一维展开的方式,对应的是列优先。C/C++中使用的是行优先方式(row major),Matlab、Fortran使用的是列优先方式(column major),PyTorch中Tensor底层实现是C,也是使用行优先顺序,因此也称为 C order。
为为为什么
2022/08/05
2.3K0
numpy 和 pytorch tensor 的内存连续性 contiguous
Python NumPy数组标记系统与内存布局
NumPy 是 Python 中处理多维数组和矩阵计算的强大工具,其核心优势之一在于高效的内存布局和灵活的标记系统。理解 NumPy 的数组标记(flags)和内存布局(memory layout),不仅有助于优化代码性能,还能帮助我们更好地处理复杂的数据操作。
sergiojune
2025/02/04
1220
Python NumPy数组标记系统与内存布局
NumPy 最详细教程(1):NumPy 数组
Numpy 是 Python 中科学计算的核心库,NumPy 这个词来源于 Numerical 和 Python 两个单词。它提供了一个高性能的多维数组对象,以及大量的库函数和操作,可以帮助程序员轻松地进行数值计算,广泛应用于机器学习模型、图像处理和计算机图形学、数学任务等领域。
丹枫无迹
2019/03/20
3.8K0
NumPy Essentials 带注释源码 二、NumPy 数组对象
# 来源:NumPy Essentials ch2 数组索引和切片 # 创建 100x100 个 0~1 随机数 x = np.random.random((100, 100)) # 取第 42 行 87 列的元素(从零开始) y = x[42, 87] # 取第 k 行的所有元素 # 等价于 x[k] 和 x[k, ...] print(x[k, :]) a = np.array([[10 * y + x for x in range(6)] for y in range(6)]) '''
ApacheCN_飞龙
2019/02/15
5560
软件测试|Python科学计算神器numpy教程(二)
上一篇文章我们介绍了numpy的安装和ndarray的部分知识,本篇文章我们来介绍一下numpy的数组的常用属性以及创建数组相关内容。
霍格沃兹测试开发Muller老师
2023/07/31
1870
《利用Python进行数据分析·第2版》 附录A NumPy高级应用A.1 ndarray对象的内部机理A.2 高级数组操作A.3 广播A.4 ufunc高级应用A.5 结构化和记录式数组A.6 更多
在这篇附录中,我会深入NumPy库的数组计算。这会包括ndarray更内部的细节,和更高级的数组操作和算法。 这章包括了一些杂乱的章节,不需要仔细研究。 A.1 ndarray对象的内部机理 NumPy的ndarray提供了一种将同质数据块(可以是连续或跨越)解释为多维数组对象的方式。正如你之前所看到的那样,数据类型(dtype)决定了数据的解释方式,比如浮点数、整数、布尔值等。 ndarray如此强大的部分原因是所有数组对象都是数据块的一个跨度视图(strided view)。你可能想知道数组视图arr[
SeanCheney
2018/04/24
5K0
《利用Python进行数据分析·第2版》 附录A NumPy高级应用A.1 ndarray对象的内部机理A.2 高级数组操作A.3 广播A.4 ufunc高级应用A.5 结构化和记录式数组A.6 更多
NumPy 高级教程——内存布局
NumPy 提供了强大的多维数组操作功能,并允许用户控制数组在内存中的布局方式。内存布局对于数组的性能和内存消耗都有重要影响。在本篇博客中,我们将深入介绍 NumPy 中的内存布局,包括连续内存布局(C顺序)和分散内存布局(Fortran顺序),并通过实例演示如何操作数组的内存布局。
Echo_Wish
2024/01/04
2600
NumPy Essentials 带注释源码 四、NumPy 核心和模块
# 来源:NumPy Essentials ch4 步长 # 步长是每个维度相邻两个元素的偏移差值 import numpy as np x = np.arange(8, dtype = np.int8) x # array([0, 1, 2, 3, 4, 5, 6, 7]) # x 是一维数组,步长为 1,因为 int8 占一个字节 x.strides # (1,) # data 属性可以观察原始数据 str(x.data) # '\x00\x01\x02\x03\x04\x05\x06\x0
ApacheCN_飞龙
2019/02/15
5920
Python数据分析(4)-numpy数组的属性操作
numpy数组也就是ndarray,它的本质是一个对象,那么一定具有一些对象描述的属性,同时,它还有元素,其元素也有一些属性。本节主要介绍ndarray以及其元素的属性和属性的操作。
锦小年
2019/05/26
1.2K0
揭秘 NumPy 的形
使用 NumPy, TensorFlow, Pytorch ,我们经常会使用数组的 reshape 操作,变化数组为各种 shape.
double
2020/03/18
3780
揭秘 NumPy 的形
理解numpy中ndarray的内存布局和设计哲学
ndarray是numpy中的多维数组,数组中的元素具有相同的类型,且可以被索引。
李拜六不开鑫
2020/02/17
1.5K0
数据科学 IPython 笔记本 9.1 NumPy
9.1 NumPy 致谢:派生于 Olivier Grisel 分享的 scikit-learn 和 IPython 并行机器学习 译者:飞龙 协议:CC BY-NC-SA 4.0 NumPy 数组,dtype和形状 常见数组操作 原地修改形状和更新 合并数组 创建示例数据 import numpy as np NumPy 数组,dtype和形状 a = np.array([1, 2, 3]) print(a) print(a.shape) print(a.dtype) ''' [1 2 3]
ApacheCN_飞龙
2022/12/02
2850
python的NumPy使用
Numpy 的主要用途是以数组的形式进行数据操作。 机器学习中大多数操作都是数学操作,而 Numpy 使这些操作变得简单!所以专门学习记录一下numpy是十分有必要的!
用户7886150
2021/01/03
1.9K0
Python Numpy数组内存布局与性能优化实战
在使用Python进行数据分析和科学计算时,Numpy是处理多维数组的强大工具。对于大规模的数据处理,理解Numpy数组的内存布局可以优化性能,提升计算效率。Numpy数组在内存中是如何组织的,直接影响到数组操作的速度、数据存取的方式以及内存使用的效率。
sergiojune
2024/10/14
2880
Python Numpy数组内存布局与性能优化实战
NumPy 1.26 中文文档(五)
此参考手册详细介绍了 NumPy 中包含的函数、模块和对象,描述了它们的作用和功能。要了解如何使用 NumPy,请参阅完整文档。
ApacheCN_飞龙
2024/06/28
2740
NumPy 1.26 中文文档(五)
Python NumPy缓存优化与性能提升
NumPy 是 Python 中进行科学计算和数据处理的核心库,其强大的多维数组操作功能让其在计算密集型任务中表现优异。然而,当处理大规模数据时,性能问题可能成为瓶颈。合理地利用 NumPy 的缓存机制和优化策略,可以显著提升计算效率。
sergiojune
2024/12/23
2280
Python NumPy缓存优化与性能提升
NumPy学习笔记(一)
# NumPy ### 安装 - 通过安装Anaconda安装NumPy,一个开源的Python发行版本,其包含了conda、Python等180多个科学包及其依赖项,包含了大量的科学计算相关的包,其中就包括NumPy - 通过pip安装, - 在windows中,控制台中输入命令安装 ```python >pip install numpy ``` - 在ubuntu中,控制台输入命令安装 ```python XXX:~/Desktop$sud
py3study
2020/01/17
6180
Numpy 修炼之道 (2)—— N维数组 ndarray
ndarray中的每个元素在内存中使用相同大小的块。 ndarray中的每个元素是数据类型对象的对象(称为 dtype)。
abs_zero
2018/04/11
7610
Numpy 修炼之道 (2)—— N维数组 ndarray
NumPy 1.26 中文文档(四十六)
当构建 NumPy 时,将记录有关系统配置的信息,并且通过使用 NumPy 的 C API 的扩展模块提供。这些信息主要在 numpyconfig.h 中定义(包含在 ndarrayobject.h 中)。公共符号以 NPY_* 为前缀。NumPy 还提供了一些用于查询正在使用的平台信息的功能。
ApacheCN_飞龙
2024/07/26
1240
Python3快速入门(十二)——Num
NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,同时对数组运算提供了大量的数学函数库。 Numpy 是一个运行速度非常快的数学库,内部解除了CPython的GIL,运行效率极好,主要用于数组计算,是大量机器学习框架的基础库,NumPy主要包括如下: (1)强大的N维数组对象 ndarray (2)广播功能函数 (3)整合 C/C++/Fortran 代码的工具 (4)线性代数、傅里叶变换、随机数生成等功能。 NumPy 通常与 SciPy(Scientific Python)和 Matplotlib(绘图库)组合使用,用于替代 MatLab。
py3study
2020/01/06
4.7K0
推荐阅读
相关推荐
numpy 和 pytorch tensor 的内存连续性 contiguous
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验