点击上方“朱小厮的博客”,选择“设为星标”

后台回复"1024"领取公众号专属资料

欢迎跳转到本文的原文链接:https://honeypps.com/backend/row-major-and-column-major-and-iliffe-vector/

本文以一个简单的程序开头——数组赋值:

int LEN = 10000;
int[][] arr = new int[LEN][LEN];for (int i = 0; i < LEN; i++) {for (int j = 0; j < LEN; j++) {arr[i][j] = 1;}
}

示例中虽然采用了Java,但是熟悉其他编程语言的同学可以自行脑补成自己熟悉的语言,如C/C++、Go、Python之类的,这里的知识点不限制在语言层级。

我们在使用这种for循环的时候,是否会习惯性地使用arr[i][j]的这种写法? 其实很多开源代码、技术书籍示例中都是如此。你是否还考虑过还有如下这种写法,即将 arr[i][j] 替换成 arr[j][i] :

int LEN = 10000;
int[][] arr = new int[LEN][LEN];for (int i = 0; i < LEN; i++) {for (int j = 0; j < LEN; j++) {arr[j][i] = 1;}
}

两段代码功能完全一样,究竟有何区别?两者性能会有数十倍或者数百倍之差。

有些同学看到这里,直接祭出IDE,运行试了一下,发现第一段代码的性能最优,所以很快地得出了a[i][j]最优的结论。不过也会有同学会运行出第二段代码性能更优的结果,即a[j][i]最优。这到底是怎么回事呢?

从语言本身看,这个问题的要点在于语言怎样实现矩阵 arr[M][N] 的存放。有两种最基本的存放方式:一种是第1下标优先存放;另一种是第2下标优先存放。也就是一般所说的行优先(Row-major)和列优先(Column-major)。

举个例子,对于下面的数组:

可以有两种存储方式:左为列优先,右为行优先。

行优先存储,顾名思义,就是一行的数据存放在一起,然后逐行存放。列优先存储,就是每一列的数据是存储在一起的,一列一列地存放在内存中。这两种存储方法,对于编写遍历二维矩阵的循环语句,还是有一定影响的。比如,如果是按行优先存储的,那么在遍历时,一行一行的读取数据,肯定比一列一列地读取整个数组,要方便许多(前者连续访问内存,有利于CPU高速缓存,后者不联系访问内存,会引起频繁更新高速缓存)。

行优先(Row-major)或者列优先(Column-major)没有好坏,但其直接涉及到对内存中数据的最佳存储访问方式。因为在内存使用上,程序访问的内存地址之间连续性越好,程序的访问效率就越高;相应地,程序访问的内存地址之间连续性越差。所以,我们应该尽量在行优先机制的编译器,比如C/C++、Objective-C(for C-style arrays)、Pascal等等上,采用行优先的数据存储方式;在列优先机制的编译器,比如Fortune、Matlab、R等等上,采用列优先的数据存储方式。但这种思想渗透到编程中之后,代码的质量就会提高一个档次。

这里没有提到市场占有率很高的Java语言,那么它们属于行优先还是列优先呢?

答案:两者都不是。

密集数组存储的一个典型替代方案是使用伊利夫向量(Iliffe vector),它通常将元素存储在连续的同一行中(如同Row-major顺序),但不存储行本身。

什么是Iliffe向量?在计算机编程中,Iliffe向量是一种用于实现多维数组的数据结构。n维数组的Iliffe向量(其中n≥2)由指向(n - 1)维数组的指针的向量(或1维数组)组成。它们通常用于避免在对数组元素执行地址计算时执行昂贵的乘法操作。它们还可用于实现交错数组,如三角形数组、三角形矩阵和其他各种不规则形状的数组。数据结构以John K. Iliffe命名。

它们的缺点包括需要多个链接指针来访问一个元素,以及需要额外的工作来确定n维数组中的下一行,以允许优化编译器预取它。在CPU明显快于主存的系统中,这两个问题都是延迟的来源。

在Java、Python(多维列表)、Ruby、Visual Basic . net、Perl、PHP、JavaScript、Objective-C(当使用NSArray时,不是一个Row-magor C-Style的数组)、Swift和Atlas Autocode等语言中的多维数组被实现为Iliffe向量。利用Iliffe向量实现OLAP产品全息的稀疏多维阵列。

回到开头,如果使用Java语言运行文中开头的2段代码,哪个更叫高效呢?请在留言区留下你的答案和思考。

欢迎跳转到本文的原文链接:https://honeypps.com/backend/row-major-and-column-major-and-iliffe-vector/

想知道更多?描下面的二维码关注我

后台回复”加群“获取公众号专属群聊入口

当当优惠码福利来一波!当当全场自营图书5折,用优惠码:TASEMU(长按复制),满200(原价400)再减30,相当于170=400,四折多一点。使用渠道:当当小程序或当当APP。使用时间:4/10-4/23。

【原创系列 | 精彩推荐】

  • Paxos、Raft不是一致性算法嘛?

  • 越说越迷糊的CAP

  • 面试官居然问我Raft为什么会叫做Raft!

  • 面试官给我挖坑:URI中的//有什么用

  • 网关Zuul科普

  • 网关Spring Cloud Gateway科普

  • 分布式事务科普——初识篇

  • 分布式事务科普——终结篇

>>> 字节跳动社招内推入口 <<<

>>> 字节跳动校招内推入口 <<<

朕已阅 

面试官给我挖坑:a[i][j] 和 a[j][i] 有什么区别?相关推荐

  1. 面试官给我挖坑:单台服务器并发TCP连接数到底可以有多少 ?

    点击上方"朱小厮的博客",选择"设为星标" 后台回复"k8s"领取阿里云<深入浅出k8s.pdf> 欢迎跳转到本文的原文链接:h ...

  2. 面试官给我挖坑:URI中的 “//” 有什么用?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 我们在浏览网页的时候,需要在浏览器中输入http://或者http ...

  3. firefox 接受post 不完整_面试官想听到的GET和POST两种基本请求方法的区别

    前言 HTTP定义了与服务器交互的不同方法,最常用的方法有四种Put,Delete.post,get,即增删改查. 1.Get,它用于获取信息,它只是获取.查询数据,也就是说它不会修改服务器上的数据, ...

  4. 面试官:要不讲讲 Cookie、Session、Token、JWT之间的区别?

    击上方"朱小厮的博客",选择"设为星标" 后台回复"加群",加入组织 来源:22j.co/btPm 什么是认证(Authentication ...

  5. “约见”面试官系列之常见面试题第二十三篇之get和post区别(建议收藏)

    POST和GET是HTTP协议中最常用的两种传参方式,这里小小总结一下两者的区别,欢迎补充~! 请求方式 GET POST 参数位置 url的query中 一般在content中,query也可 参数 ...

  6. 面试官给我挖坑:rm删除文件之后,空间就被释放了吗?

    在Linux,你是不是曾经天真的以为,使用rm删除一个文件,占用的空间就释放了?事情可能不是常常如人意. 产生一个指定大小的随机内容文件 我们先看一下当前各个挂载目录的空间大小: $ df -h /d ...

  7. 面试官:为什么 wait() 方法需要写在循环里?

    点击上方"朱小厮的博客",选择"设为星标" 后台回复"加群",加入新技术 来源:8rr.co/6cj5 问:为什么是 while 而不是 i ...

  8. 面试官:Thread.sleep(0) 有什么用?

    点击上方"朱小厮的博客",选择"设为星标" 后台回复"加群",加入新技术 我们可能经常会用到 Thread.Sleep 函数来吧使线程挂起一 ...

  9. 面试官:为什么SpringBoot的 jar 可以直接运行?

    点击上方"朱小厮的博客",选择"设为星标" 后台回复"k8s"领取阿里云<深入浅出k8s.pdf> 来自:rrd.me/gEAS ...

最新文章

  1. 犹豫了许久,还是写个年总结记录一下吧
  2. [HNOI2002]彩票
  3. Android分享功能,微博、QQ、QQ空间等社交平台分享之入门与进阶
  4. 视觉SLAM总结——LSD SLAM中关键知识点总结
  5. linux cpu频率软件,linux cpu频率控制
  6. 使用Julia进行图像处理--使用形态学运算进行图像调整
  7. 站闻资讯项目开发个人总结
  8. 栈实现10进制到8进制的转换
  9. 微博中的长链接与短链接
  10. modelsim se 10.5安装教程
  11. OTT广告系统设计与实现
  12. 【评测】照胶的仪器选购
  13. python3.8零基础入门教程_正版 Python 3.8编程快速入门 针对wan全零基础入门的读者 采用*小化安装+极简代码的教学...
  14. 谈谈令你印象深刻的技术问题
  15. Ajax 改造,第 3 部分: 用 jQuery、Ajax 选项卡和照片 carousel 改进现有的站点
  16. 一年365天,把1.0作为每天的能力值基础,每天原地踏步 则能力值为1.0,如果每天努力一点点则能力值提高1%,每天再努力一点则能力值提高2%,那一年后,这3种行为收获的成果相差多少呢?
  17. MongoDB 分片迁移
  18. 计算机管理员已禁用了teredo,Win7提示设备管理器中出现叹号设备“Teredo tunneling pseudo-interface”...
  19. 冰冻三尺非一日之寒-自学篇 浅谈个人学习方法
  20. 微信小程序超级占内存_实测:微信小程序占多少内存?或许真没有你想象的那么“小”!...

热门文章

  1. 华为手机记事本导出_涨知识!原来华为手机自带的录音转文字这么好用,秒变会议神器...
  2. Java8函数式编程(4)--终止操作(源码)
  3. java进制原码_Java 一一 进制、原码 反码 补码、移位操作
  4. POJ 3259 Wormholes【最短路/SPFA判断负环模板】
  5. 入门设计模式之建造者模式
  6. 你知道我们平时在CSS中写的%都是相对于谁吗?
  7. 多网卡无法上外网的解决
  8. 继承的基本概念(1)
  9. doctype声明的意义
  10. Tomcat配置虚拟主机的两种方式