针对cache,将代码中的循环语句进行优化

今天上计组课的时候,老师讲了cache的原理。暑假在读《c++反汇编原理》时对这一块很不理解,故今日理解后将其记下。
cache是计算机内的高速缓冲器。
百度百科对cache的解释是:
Cache存储器:电脑中为高速缓冲存储器,是位于CPU和主存储器DRAM(Dynamic Random Access Memory)之间,规模较小,但速度很高的存储器,通常由SRAM(Static Random Access Memory 静态存储器)组成。它是位于CPU与内存间的一种容量较小但速度很高的存储器。CPU的速度远高于内存,当CPU直接从内存中存取数据时要等待一定时间周期,而Cache则可以保存CPU刚用过或循环使用的一部分数据,如果CPU需要再次使用该部分数据时可从Cache中直接调用,这样就避免了重复存取数据,减少了CPU的等待时间,因而提高了系统的效率。Cache又分为L1Cache(一级缓存)和L2Cache(二级缓存),L1Cache主要是集成在CPU内部,而L2Cache集成在主板上或是CPU上。图片来自百度百科cpu在一定时间内,只对主存的局部地址进行访问。这是由于指令和数据在主存内是连续存放的,并且有些指令和数据往往会被多次调用(比如循坏代码块中的内容)。这说明指令和数据在主存内是相对聚集的,使得cpu在执行程序时,访问存取数据具有相对局部性,这称为程序访问的局部原理。那么根据这一原理,提前将cpu近期将用到的程序和数据载入到cache内,使cpu在一定时间内只访问cache。由于cpu访问cache的速度比访问主存的速度快,便能提高程序运行的效率。
代码中的循环语句,执行一次之后,主存便会将相关代码送入到cache内,不断执行,执行到退出循环时,cache命中失误,cpu只能从主存中读取相关代码。
下面举一个小例子

int main()
{
	int i ,j;
	for(i = 0; i < 10;i++)
	{
		for(j = 0;j < 10000;j++)
		{
			//代码块
		}
	}
	return 0}
int main()
{
	int i ,j;
	for(i = 0; i < 10000;i++)
	{
		for(j = 0;j < 10;j++)
		{
			//代码块
		}
	}
	return 0}

在大多数情况下,这两代码的执行结果是相同的,但是大循环在内部的代码效率更高,这是为什么呢?
当内循环为10000次时,cache命中次数为10000,未命中次数为1,那么1 * 外循环次数(10)= 10,未命中次数为10。
当内循环为10次时,cache命中次数为10,未命中次数为1,那么1 * 外循环次数(10000)= 10000,未命中次数为10000。
我们可以来算一下cpu的访问效率。
在一个程序执行期间,设Nc为访问cache的总命中次数,Nm为访问主存的总次数,则命中率h为

					h=Nc/(Nc+Nm)

设Tc为命中时,cache的访问时间,Tm为未命中时的主存访问时间,1-h表示未命中率,则cache-主存系统的平均访问时间ta为

				Ta=hTc+(1-h)Tm

用e表示访问效率,则有

			e = Tc/Ta * 100% = Tc/[hTc+(1-h)Tm] * 100%

设Tc = 20ns,Tm = 100ns
则大循环在内的命中率:
h1 = 100000/(100000+10) = 0.9999000099990001
访问效率:
e1 = 20/[h1 * 20 + (1-h1) * 100] = 0.9996001999000
小循环在内的命中率:
h2 = 100000/(100000+10000) = 0.9090909090909091
访问效率:
e2 = 20/[h2 * 20 + (1-h2) * 100] = 0.73333333333333333
可以看出,循环语句嵌套时,大循环为内循环时,效率更高,因此在写代码时,要注意将大循环放在内部,程序的执行效率更高。
欢迎批评指正。

发布了3 篇原创文章 · 获赞 1 · 访问量 105
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 游动-白 设计师: 上身试试

分享到微信朋友圈

×

扫一扫,手机浏览