1. 名词

Clock Cycle Time

  • 主频的概念大家接触的比较多,而 CPU 的 Clock Cycle Time(时钟周期时间),等于主频的倒数,意思是 CPU 能够识别的最小时间单位,比如说 4G 主频的 CPU 的 Clock Cycle Time 就是 0.25 ns,作为对比,我们墙上挂钟的Cycle Time 是 1s
  • 例如,运行一条加法指令一般需要一个时钟周期时间

CPI

  • 有的指令需要更多的时钟周期时间,所以引出了 CPI (Cycles Per Instruction)指令平均时钟周期数

IPC

  • IPC(Instruction Per Clock Cycle) 即 CPI 的倒数,表示每个时钟周期能够运行的指令数

CPU 执行时间

  • 程序的 CPU 执行时间,即我们前面提到的 user + system 时间,可以用下面的公式来表示

程序 CPU 执行时间 = 指令数 * CPI * Clock Cycle Time

2. 指令重排序优化

事实上,现代处理器会设计为一个时钟周期完成一条执行时间最长的 CPU 指令。为什么这么做呢?可以想到指令
还可以再划分成一个个更小的阶段,例如,每条指令都可以分为: 取指令 - 指令译码 - 执行指令 - 内存访问 - 数据写回 这 5 个阶段
指令重排的前提是,重排指令不能影响结果,例如

  1. // 可以重排的例子
  2. int a = 10; // 指令1
  3. int b = 20; // 指令2
  4. System.out.println( a + b );
  5. // 不能重排的例子
  6. int a = 10; // 指令1
  7. int b = a - 5; // 指令2

3. 高并发情况可能出现的问题

  1. int num = 0;
  2. boolean ready = false;
  3. // 线程1 执行此方法
  4. public void actor1(I_Result r) {
  5. if(ready) {
  6. r.r1 = num + num;
  7. } else {
  8. r.r1 = 1;
  9. }
  10. }
  11. // 线程2 执行此方法
  12. public void actor2(I_Result r) {
  13. num = 2;
  14. ready = true;
  15. }

上述代码的r1最终会有几种结果呢,但是让人没想到的结果还可能会是0
这种情况下是:线程2 执行 ready = true,切换到线程1,进入 if 分支,相加为 0,再切回线程2 执行 num = 2,这就是指令重排可能会导致的情况