前往小程序,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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
vue课程学习笔记归纳
特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性!!!
Akilar
2023/04/30
2.3K0
后端 学习 前端 Vue 框架基础知识
里面放入定义好的数据,data:{name:“”,list:[{id:“”,name:“”}]},全部都写成json格式的
RAIN7
2022/10/04
1.9K0
后端 学习 前端 Vue 框架基础知识
《进阶篇第9章》学习vuex知识点后练习:把求和案例改成vuex模块化编码
<font color='red'>旧代码:无论设置 value="1"还是 value=1都无效</font>
刘大猫
2024/10/15
1170
「后端小伙伴来学前端了」Vuex进阶操作,让你的代码更加高效(简称如何学会偷懒 【手动狗头】)
前一篇写了Vuex基本使用,用起来还稍稍有些繁琐,代码有很多 冗余的地方,这篇就带着大家用更简单的方式来使用Vuex(其实就是怎么更好的偷懒,用更少的代码来完之前的事情)
宁在春
2022/10/31
4720
「后端小伙伴来学前端了」Vuex进阶操作,让你的代码更加高效(简称如何学会偷懒 【手动狗头】)
第十三章:vuex状态(数据)管理
概念:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化,可以用于组件之间的通信。
张哥编程
2024/12/13
1920
Vuex代码优化及模块化
代码优化 01 - 为什么需要优化 使用Vuex之后会发现在使用store管理的数据时有些繁琐,模板的插值表达式中,每个被使用的数据都必须$store.state.属性名,假如我们有100个数据,$store.state就得写100遍,感觉非常没必要,造成了资源浪费,也会使加载速度变慢。 这时就会有人想到Vue的计算属性computed,写着写着又发现,即使是计算属性的简写形式也是每一个数据都需要写一个方法的,依然很繁琐。 接下来要说的就是Vuex给我们提供了辅助函数(mapState等),可以帮助我们生成计算属性等,极大的减少了代码量和工作量,又能少掉几根头发啦啦啦。 02 - 使用方法 引入辅助函数
全栈开发日记
2022/05/13
4290
Vue学习笔记与常用操作
第一种:使用custom-classes-transition,需要在不同的载入,载出动画上加-enter和-leave后缀
JanYork_简昀
2022/05/18
2K0
Vue学习笔记与常用操作
后端小白的 Vue 入门笔记 —— 进阶篇
出处:https://www.cnblogs.com/ZhuChangwu/p/11325489.html
IT技术小咖
2019/08/20
2.1K0
《进阶篇第9章》学习vuex知识点后练习:把求和案例改成mapState与mapGetters
<font color='red'>旧代码:无论设置 value="1"还是 value=1都无效</font>
刘大猫
2024/10/17
910
《进阶篇第9章》学习vuex知识点后练习:把求和案例改成多组件共享数据
<font color='red'>旧代码:无论设置 value="1"还是 value=1都无效</font>
刘大猫
2024/10/16
1090
Vue 全家桶,深入Vue 的世界
可以看到text值的变化是0 5 10 15 … 而并没有出现 0 1 2 3 … 这样连续的变化
FinGet
2019/06/28
2.8K0
Vue 全家桶,深入Vue 的世界
vue组件之间的传值通信(vue props 对象 默认值)
朋友们可以百度下 Session Storage(程序退出销毁) 和 Local Storage(长期保存) 的区别。
全栈程序员站长
2022/08/01
2.1K0
vue组件之间的传值通信(vue props 对象 默认值)
「vue基础」写给 Vuex 初学者的使用指南
大家好,在前面的几篇文章里我们一起学习了Vue相关的基础知识,想复习基础的同学可以点击文末链接进行回顾。今天我们将学习 Vue 的 State Management(状态管理):Vuex,我们在构建大型应用时 ,State Management 的处理至关重要。
前端达人
2021/01/02
1.3K0
「vue基础」写给 Vuex 初学者的使用指南
闲聊vue版本差异和开发中不太容易注意的点(基础篇)
原来tom的位置就会被jim给替换掉,这是我们不愿意看到的情况,当我们加上key的时候,你选中的就是你选中的,☑️tom不会被因为位置变化而变化
何处锦绣不灰堆
2022/09/20
1.3K0
Vue总汇
当我们拿到别人的项目的时候,一般情况下是没有node_modules包。需要使用命令去初始化依赖。
世间万物皆对象
2024/03/20
1410
Vuex 深入浅出超详细
Vuex 官网🔗: Vuex 是一个专为 Vue.js 应用程序设计的状态管理库,它提供了一种集中式管理 应用中的状态;
Java_慈祥
2024/08/10
1420
Vuex 深入浅出超详细
【初级】个人分享Vue前端开发教程笔记
每天学习编程,让你离梦想更新一步,感谢不负每一份热爱编程的程序员,不论知识点多么奇葩,和我一起,让那一颗四处流荡的心定下来,一直走下去,加油,2021加油!
达达前端
2021/02/04
4.9K0
三年经验前端vue面试记录
vue-router中两个重要组件router-link和router-view,分别起到导航作用和内容渲染作用,但是回答如何生效还真有一定难度
bb_xiaxia1998
2022/10/31
2.2K0
Vue(下)
日常开发中,通常设置一个app组件作为主组件(相当于单文件组件的App.vue):
十玖八柒
2022/08/01
2.3K0
Vue(下)
vue-axios-vuex-全家桶
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。简单来说就是前端最火最简单的一个http请求解决方案。
达达前端
2021/09/08
2.8K0
推荐阅读
相关推荐
vue课程学习笔记归纳
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验