【19】循环优化

为了提升循环的效率,编译器会针对循环的编译进行多种方式的优化,比如:循环无关代码外提,循环展开等

1.循环无关代码外提

  • 循环无关代码:循环中值不会发生变化的表达式。通过将这些循环无关的代码提出循环外,可避免重复执行这些表达式,实现性能提升。
int foo(int x, int y, int[] a) {
	int sum = 0;
	for ( int i = 0; i<a.length; i++) {
		sum += x * y + a[i];
	}
	return sum;
}

循环无关代码:(1)表达式 :x * y (2)循环判断条件:a.length

优化后代码如下:

int foo(int x, int y, int[] a) {
	int sum = 0;
	int t0 = x * y;
	int t1 = a.length;
	for ( int i = 0; i<t1; i++) {
		sum += t0 + a[i];
	}
	return sum;

2.循环展开

  • 循环展开:在循环体中重复多次循环迭代,并减少循环次数的编译优化。
int foo(int x, int y, int[] a) {
	int sum = 0;
	for ( int i = 0; i< 64 ; i++) {
		sum += (i % 2 == 0) ? a[i] : -a[i];
	}
	return sum;
}

经过一次展开后,形成如下代码

int foo(int x, int y, int[] a) {
	int sum = 0;
	for ( int i = 0; i< 64 ; i += 2) { // 注意这里的步数是2
		sum += (i % 2 == 0) ? a[i] : -a[i];
		sum += ((i+1% 2 == 0) ? a[i+1] : -a[i+1];
	}
	return sum;
}

当循环的数目是固定值,且非常小时,即时编译器会将循环全部展开,此时,原本循环中的循环判断语句就不存在了,取而代之的是若干个顺序执行的循环体。

int foo(int[] a) {
	int sum = 0;
	for( int i = 0 ;  i<4 ;i++ ) {
		sum += a[i];
	}
	return sum;
}

完全展开后

int foo(int[] a) {
	int sum = 0;
	sum += a[0];
	sum += a[1];
	sum += a[2];
	sum += a[4];
	return sum;
}

即使编译器会在循环体的大小和循环展开次数之间做出权衡。

3.循环判断外提

  • 将循环中的if语句外提至循环之前,并且在该if语句的两个分支中分别放置一份循环代码
int foo(int[] a) {
	int sum = 0;
	for( int i = 0 ;  i<a.length ;i++ ) {
		if(a.length > 4) {
			sum += a[i];
		} else {
			sum += a[i] + 1;
		}
	}
	return sum;
}

经过优化后

int foo(int[] a) {
	int sum = 0;
	if(a.length > 4) {
		for( int i = 0 ;  i<a.length ;i++ ) {
			sum += a[i];
		} 
	} else {
		for( int i = 0 ;  i<a.length ;i++ ) {
			sum += a[i] + 1;
		} 
	}
	
	return sum;
}

4.循环剥离

  • 循环剥离:将循环的前几个迭代或者后几个迭代剥离出循环的优化方式。背景是循环的前几个迭代或后几个迭代都包含特殊处理。通过将这几个特殊的迭代逻辑剥离后,原本的循环体的规律性更加明显,从而触发进一步的优化。
int foo(int[] a) {
	int sum = 0;
	int j = 0;
	for( int i = 0 ;  i<a.length ;i++ ) {
		sum += a[j];
		j = i;
	}
	return sum;
}

通过剥离第一个迭代,代码如下:

int foo(int[] a) {
	int sum = 0;
	if(0 < a.length) {
		sum += a[0];
		for( int i = 1;  i<a.length ;i++ ) {
			sum += a[i-1];
		}
	}
	return sum;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值