目录
1.1.java处理中,计算阶乘,为什么展开循环可以提高效率
====
通过展开循环,提高效率。
(算法,CPU原理)
展开循环可以提高效率的原因是避免了重复的循环操作。在计算阶乘的过程中,我们需要对一个数从1乘到该数本身,如果使用循环来实现这个操作,就需要每次都进行一次循环迭代,直到达到该数。而展开循环的方式,可以直接将每一次循环的结果串联起来,避免了重复的循环操作。
---
举个例子,假设要计算5的阶乘。使用循环的方式,需要进行5次循环迭代,分别计算1x2、2x3、3x4、4x5,最后得到120。而展开循环的方式,可以直接计算1x2x3x4x5,得到结果120,避免了重复的循环操作。
--
因此,展开循环可以减少循环迭代次数,提高运算效率。但需要注意的是,展开循环在处理大数阶乘时可能会造成溢出问题,需要进行适当的优化处理。
从CPU流水线的角度来看,展开循环可以提高效率的原因是减少了分支(branch)导致的流水线停顿(pipeline stall)。
----
在计算阶乘的过程中,循环结构通常会引入条件分支,用于判断循环是否继续。当分支预测(branch prediction)失败时,CPU的流水线会发生停顿,等待分支判断结果返回。这会导致流水线中断,浪费了一些CPU周期。
----
而如果采用展开循环的方式,即在代码中展开多个循环迭代,相当于将多个循环迭代的结果直接写入代码中。这样就避免了循环和条件分支的存在,减少了分支预测失败的机会,减少了流水线停顿。
---
通过减少流水线停顿,CPU可以更充分地利用流水线的并行性和吞吐量,提高指令的执行效率,加快计算阶乘的速度。
---
但是需要注意,展开循环也会增加代码量,可能会导致代码膨胀和缓存不命中等问题,因此在选择是否展开循环时需要综合考虑代码大小、缓存使用情况以及具体的计算规模来做出决策。
=======
package com.sxz.study.alogrithm;
public class TestAlogrithom {
public static void main(String[] args) {
long timeBegin = 0;
long timeEnd =0;
timeBegin = System.currentTimeMillis();
long result1 = calc001(1000000000);
System.out.println(result1);
timeEnd = System.currentTimeMillis();
System.out.println(timeEnd-timeBegin);
timeBegin = System.currentTimeMillis();
long result2 = calc002(1000000000);
System.out.println(result2);
timeEnd = System.currentTimeMillis();
System.out.println(timeEnd-timeBegin);
}
public static long calc001(int sumNumber) {
long count = 0;
for (int i = 1; i <= sumNumber; i++) {
count += i;
}
return count;
}
public static long calc002(int sumNumber) {
long count1 = 0, count2 = 0, count3 = 0, count4 = 0;
// 假设,sumNuber 是4的倍数
for (int i = 1; i <= sumNumber; i+=4) {
count1 += i;
count2 += i+1;
count3 += i+2;
count4 += i+3;
}
return count1 + count2 + count3 + count4;
}
}
性能提高 了近14% (299 ? 258)?
(299-258)/ 299 = 13.71%
299 / 258 =1.1589
改善后,速度是之前的1.16倍
500000000500000000
299
500000000500000000
258
----------------------
package com.sxz.study.alogrithm;
import java.math.BigDecimal;
public class TestAlogrithom2 {
public static void main(String[] args) {
long timeBegin = 0;
long timeEnd =0;
timeBegin = System.currentTimeMillis();
BigDecimal result1 = calc001(10000);
System.out.println(result1);
timeEnd = System.currentTimeMillis();
System.out.println(timeEnd-timeBegin);
timeBegin = System.currentTimeMillis();
BigDecimal result2 = calc002(10000);
System.out.println(result2);
timeEnd = System.currentTimeMillis();
System.out.println(timeEnd-timeBegin);
}
public static BigDecimal calc001(int sumNumber) {
BigDecimal count = new BigDecimal(1);
for (int i = 1; i <= sumNumber; i++) {
count = count.multiply(new BigDecimal(i));
}
return count;
}
public static BigDecimal calc002(int sumNumber) {
BigDecimal count1 = new BigDecimal(1);
BigDecimal count2 = new BigDecimal(1);
BigDecimal count3 = new BigDecimal(1);
BigDecimal count4 = new BigDecimal(1);
// 假设,sumNuber 是4的倍数
for (int i = 1; i <= sumNumber; i+=4) {
count1 = count1.multiply(new BigDecimal(i));
count2 = count2.multiply(new BigDecimal(i+1));
count3 = count3.multiply(new BigDecimal(i+2));
count4 = count4.multiply(new BigDecimal(i+3));
}
return count1.multiply(count2).multiply(count3).multiply(count4);
}
}
性格提高了近69%%? (92 ? 29)
(92-29)/ 2 = 68.47
92/29 = 3.17
改善后,速度是之前的三倍。
2846..........0000
92
2846..........0000
29
===