1. CPU高速缓存:在计算机系统中,CPU高速缓存(英语:CPU Cache)是用于减小处理器访问内存所需平均时间的部件。在金字塔式存储体系中它位于自顶向下的第二层,仅次于CPU寄存器。其容量远小于内存,但速度却能够接近处理器的频率。当处理器发出内存访问请求时,会先查看缓存内是否有请求数据。若是存在(命中),则不经访问内存直接返回该数据;若是不存在(失效),则要先把内存中的相应数据载入缓存,再将其返回处理器。缓存之因此有效,主要是由于程序运行时对内存的访问呈现局部性(Locality)特征。这种局部性既包括空间局部性(Spatial Locality),也包括时间局部性(Temporal Locality)。有效利用这种局部性,缓存能够达到极高的命中率。(百度百科解释)。html
2.二维数组有两种遍历方式,一种是先行后列,一种是先列后行,代码实现也很简单,用两个for循环嵌套便可,表面上看来,两者时间复杂度都是O(mn),但实际上,效率的是经过内存页面交换次数和Cache命中率的高低来判断的。数组
3.先行后列的效率要高的多,这个与二维数组的存储方式有关(内存中,上一行的尾部地址和下一行的头部地址连续)。缓存
状况一:若是申请的空间在内存之中,也就是说读取只须要看cache是否命中,未命中再到内存中读取。而cache从内存中抓取通常都是整个数据块,因此它的物理内存是连续的,对于较大的数组而言,几乎读取的数据都是同行不一样列的(由于cache很小,因此对于较大的数组通常只会拿一行内的数据),而若是内循环以列的方式进行遍历的话,将会使整个缓存块没法被利用,而不得不从内存中读取数据,而从内存读取速度是远远小于从缓存中读取数据的。随着数组元素愈来愈多,按列读取速度也会愈来愈慢。优化
状况二:申请的为虚拟内存(固然程序认为仍是连续的物理内存,是操做系统在磁盘另开辟的空间),虚拟内存到物理内存须要通过地址映射,若是虚拟内存采用页式地址映射(不讨论快表技术,仅分析页表在内存中),最好的状况是每次映射的页内数据均可以被使用,这样能够减小页面调度的次数,从而提高效率。spa
例如:对于int a[128][1024];假设内存页大小为4096字节(一个int 占4个字节),该数组每行正好占据一个内存页的空间,若按先行后列遍历,外层循环每走一行,内层走过1024个元素正好一页,没发生页面调度,遍历完整个数组页面调度次数最多为128次;若按先列后行,则每遍历一个元素,都发生一次页面调度,由于列上每一个元素位于同行内(不一样页),遍历整个数组页面调度次数可能达到1024*128次;实际中因为物理内存足够(内存页较大,分配给进程的页框数多等因素),调度次数会减小不少。操作系统
简易代码(实际结果极可能由于申请内存位置不一样或内存大小而产生误差):.net
#include <stdio.h> #include <stdlib.h>
#define M 10000
#define N 20000
int main(){ int MyArray[M][N]; int i,j;
//先行后列方式遍历 for( i = 0;i < M;i++){ for(j = 0;j < N;j++){ MyArray[i][j] = 0; } } }
#include <stdio.h> #include <stdlib.h>
#define M 10000
#define N 20000
int main(){ int MyArray[M][N]; int i,j;
//先列后行方式遍历 for( i = 0;i < N;i++){ for(j = 0;j < M;j++){ MyArray[j][i] = 0; } } }
参考文章code
[1] 小白xiaoxiao.二维数组两种遍历的比较htm
http://blog.sina.com.cn/s/blog_707d31f50101j2e7.html
[2] 哆啦A熊.二维数组按行和按列遍历的效率blog
https://blog.csdn.net/shuffle_ts/article/details/89420651