先看这么一段代码:
执行 loop1()
函数,结果为:
再执行 loop2()
函数,结果为:
可以发现,明显 loop2()
函数的执行时间是 loop1()
函数的执行时间的 30 倍。
首先两个函数的循环次数是相同的,虽然最终生成的二维数组的元素内容是不一样的,但都是赋值操作,这个是不影响的。
那么为什么执行效率差距这么大呢。首先要明确一点,多维数组的初始化是建立在一维数组的初始化的基础上的,无论是一维数组还是多维数组都是线性连续存储的。通过下面这段代码可以证明:
执行结果:
可以看到这里 int 是 32 位的,地址值是连续的,每次加 4。
也就是说上面的二维数组我们可以简单看成是这样分布的:
两个函数的遍历方式如下(这里借用了网上的一张方格图片,具体链接见文末):
接下来再看一个概念:局部性原理。引用《计算机操作系统 第三版》中的内容:
早在 1968 年,Denning.P 就曾指出:程序在执行时将呈现出局部性规律,即在一较短 的时间内,程序的执行仅局限于某个部分;相应地,它所访问的存储空间也局限于某个区域。
局限性还表现在下述两个方面:
(1) 时间局限性。如果程序中的某条指令一旦执行,则不久以后该指令可能再次执行; 如果某数据被访问过,则不久以后该数据可能再次被访问。产生时间局限性的典型原因是 由于在程序中存在着大量的循环操作。
(2) 空间局限性。一旦程序访问了某个存储单元,在不久之后,其附近的存储单元也将 被访问,即程序在一段时间内所访问的地址,可能集中在一定的范围之内,其典型情况便 是程序的顺序执行。
还有一个就是 CPU 是有三级缓存的:
一级缓存速度是最快的。那么根据局部性原理,即程序在执行时将呈现出局部性规律,在一较短的时间内, 程序的执行仅局限于某个部分。第一种遍历方式是与数组的内存地址连续分配“方向”是一致的,符合局部性原理,所以第一种方式明显缓存命中率是比第二种高的,而如果缓存未命中,则 CPU 需要到内存中读取数据。这也就解释了为什么 loop1()
函数执行效率比 loop2()
效率高。
References
- 《计算机操作系统 第三版》
- https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=%E6%AD%A3%E6%96%B9%E5%BD%A2%E6%96%B9%E6%A0%BC&hs=2&pn=0&spn=0&di=89980&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&ie=utf-8&oe=utf-8&cl=2&lm=-1&cs=360342195%2C373797321&os=2520783413%2C3062160158&simid=3348372091%2C279339059&adpicid=0&lpn=0&ln=30&fr=ala&fm=&sme=&cg=&bdtype=0&oriquery=%E6%AD%A3%E6%96%B9%E5%BD%A2%E6%96%B9%E6%A0%BC&objurl=http%3A%2F%2Fdaan.1010pic.com%2Fpic3%2Fupload%2Fimages%2F201208%2F22%2Fd8f90581.png&fromurl=ippr_z2C%24qAzdH3FAzdH3Fooo_z%26e3B8a8a3tw3tw5_z%26e3Bv54AzdH3Fpt47n_t1_889n0cc%3F_%3D89bdb89bbm&gsm=1&islist=&querylist=
- https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=cpu%E4%B8%89%E7%BA%A7%E7%BC%93%E5%AD%98&step_word=&hs=0&pn=5&spn=0&di=19360&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&istype=0&ie=utf-8&oe=utf-8&in=&cl=2&lm=-1&st=undefined&cs=2018228500%2C2822356206&os=1738119642%2C1715516323&simid=3412046831%2C231956069&adpicid=0&lpn=0&ln=835&fr=&fmq=1591194222289_R&fm=&ic=undefined&s=undefined&hd=undefined&latest=undefined©right=undefined&se=&sme=&tab=0&width=undefined&height=undefined&face=undefined&ist=&jit=&cg=&bdtype=0&oriquery=&objurl=http%3A%2F%2Fimage.mamicode.com%2Finfo%2F201901%2F20190121195651921604.png&fromurl=ippr_z2C%24qAzdH3FAzdH3Fooo_z%26e3B4w4tv51j_z%26e3Bv54AzdH3Ftgu5-1jpwts-dcl9amn_z%26e3Bip4s&gsm=6&rpstart=0&rpnum=0&islist=&querylist=&force=undefined
欢迎关注公众号