python sum 数组原理_【底层原理】程序局部性原理介绍

码农有道

 

码农有道高质量技术文章目录整理(请戳我)

关于码农有道(请戳我)

什么是局部性原理

一个优秀的程序、优美的代码,往往具有良好的局部性。那么什么是程序的局部性原理呢?

程序局部性原理:是指程序在执行时呈现出局部性规律,即在一段时间内,整个程序的执行仅限于程序中的某一部分。相应地,执行所访问的存储空间也局限于某个内存区域,具体来说,局部性通常有两种形式:时间局部性和空间局部性。

时间局部性:被引用过一次的存储器位置在未来会被多次引用(通常在循环中)。

空间局部性:如果一个存储器的位置被引用,那么将来他附近的位置也会被引用。

这样说过于理论了些,例子是最好说明问题的途径,看下面一段代码:

//求数组元素之和,v为数组名,n为数组大小,int sum(int *v, int n)

{

    int i = 0;

    int sum = 0;

    for (i=0; i<n; ++i)

    {

        sum+=v[i];

    }

    return sum;

}

我们知道,数组的特点是在内存中是向下图一样连续存放的。

8f7e093e4014dfa76471e2e5d4c13ce1.png

根据代码以及局部性定义可知:

对于循环中的sum变量:有良好的时间局部性。因为在for循环结束之前,每次执行循环体都有对 sum 的访问。而 sum 没有空间局部性。因为sum 是标量(也就是说通过 sum 这个地址只能得到一个值)

对于循环体中的 v 变量:有良好的空间局部性。因为数组v是按顺序存放在内存中,每次访问 v[i]总是在 v[i-1] 的下一个位置。而v没有时间局部性,因为在循环体中,每个元素v[i]只会被访问一次。

局部性对程序效率的影响

我们再来看看一个遍历二维数组的例子:

#include <stdio.h>
#include <stdlib.h>#include <time.h>int a[500][500];//先访问行void fun_1()
{    
   int i,j;        for(i=0; i<500; i++)    
   {for(j=0; j<500; j++){    a[i][j]=i;}    
   }
}//先访问列void fun_2()
{        int i,j;      for(j=0; j<500; j++)    
   {for(i=0; i<500; i++){    a[i][j]=i;}    
   }
}int main()

{    

    clock_t start, finish;    

    double  duration;    

    start = clock();    

    fun_1();    

    finish = clock();  

    duration = (double)(finish - start) / CLOCKS_PER_SEC;    

    printf( "fun_1:  %f seconds", duration);  

         start = clock();    

        fun_2();    

        finish = clock();    

        duration = (double)(finish - start) / CLOCKS_PER_SEC;    

        printf( "fun_2:  %f seconds", duration) ;    

        return 0;

}
bogon:dataStructure lizhong$ ./test
fun_1: 0.000624 seconds
fun_2: 0.001193 seconds

上面的例子,fun_1和fun_2都是对一个二维数组进行遍历赋值。在fun_1函数的for循环体中,是以行序为主序对元素进行遍历。也就是说内层循环先访问第一行的元素,然后第二行......,而二维数组在存储器中也是按照行序为主序来进行存储的。也就是说先存储第一行,然后第二行......,如下图所示。本例中存储顺序和访问顺序一致。所以可以该程序对a[][]的引用有良好的空间局部性。

而fun_2函数只是在fun_1的基础上将求和函数中的双重循环的索引i和j调换一下位置,也就是说在对a[][]进行遍历的时候,以列序为主序。即先访问第一列,在访问第二列......,而前面讲了二维数组在存储器中也是按照行序为主序来进行存储;意味着每访问一个元素,就要跳过N个元素才能访问下一个。这种情况下没有良好的空间局部性。

6f7b6fd8cb4ef8d62cb3c9938675d697.png

再来看看运行结果,对于同一个数组,具有空间局部性的fun_1函数运行的效率几乎是没有局部性的fun_2函数的提高了一倍,至于为什么有良好局部性的程序有更好的性能,这个和计算机的缓存是息息相关的,将会在后面的文章中介绍。这篇文章且当作后文的铺垫吧。

推荐阅读:

完全整理 | 365篇高质技术文章目录整理

360°全方位解读「缓存」

GitHub 上有哪些一般人也可以用的项目?

Github 标星 4w+,如何用 Python 实现所有算法

浅谈什么是递归算法

专注服务器后台技术栈知识总结分享

欢迎关注交流共同进步

7e5b333a225f41b0c4c41bfdc0ea2ce6.png

码农有道 coding

码农有道,为您提供通俗易懂的技术文章,让技术变的更简单!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值