转载请注明出处:http://blog.csdn.net/c602273091/article/details/53606031
Memory
Memory Intro
volatile
non-volatile
Disk
磁盘容量:
传输特定扇区的数据的过程:
计算传输某个扇区所需的时间:
Locality
CPU和memory之间的吞吐量相差巨大。
这时候是局部性使得这两者间的鸿沟没有那么大。局部性就是程序倾向于使用与它最近使用过的数据和指令。局部性设计时间局部性和空间局部性。时间局部性就是最近使用过的数据或者指令有较大可能性会被重新使用。空间局部性就是指最近使用过的数据或者指令周围的数据或指令有较大的可能性被用到。
举一个例子:
那么我们如何衡量一个程序使用有局部性?请看下面的memory hierarchy。
memory hierarchy
从上图可以看出,CPU是首先从cache读取数据,所以在局部性设计方面,我们先从cache入手。
具体怎么做呢?请看CMU 18-600的cache memory这一节以及结合cache lab你就有充分的了解 Click Here
Program Optimization
Optimization Compilers
优化编译器涉及寄存器分配,代码调度。消除dead code。
看一个例子:
这样做就可以减少stall,并且不会改变它的整个逻辑流,最后各个寄存器的值都是一样的。
一般做编译机优化有资源、过程的约束。画出data flow graph可以对这个过程调度可以认识更加清晰。
所以编译器做优化一般使用的方法是代码搬移,在寄存器级别就是寄存器重命名。重命名就是在有stall这种情况下使用一些空闲的寄存去以减少程序的暂停。
以上方法会导致有时候一个寄存器的赋值需要很多寄存器的参与,为了解决这个问题,所以使用一个中间变量复制。
常用的优化小技巧
代码搬移
把循环中重复计算的值搬出去,比如:
使用简单操作代替
共享相同变量
优化块
过程调用优化
之前:
之后:
代码混叠
每次都把b[i]的值加给自己,b[i]是数组,为了索引它还要计算地址。
修改:
使用指令级并行
根据处理器结构,进行代码优化。
举个例子:
使用vector数据结构索引数据:
对一个vector进行求和之类的操作:
修改如下,这样就不需要每次做一个边界检查了。其实我觉得这个和最早的去除过程调用意思一样。
supercsala:就是一个周期执行多条指令,从指令流取出一堆指令,然后以某一个顺序执行。
比如我们做一下操作,前后是有联系的:
那么我们可以一次乘以两个数:
这样的结果就是:
浮点数的结果还是没有优化。
请看下一个,只是修改了一点点:
谁让编译器是先做括号里面的呢。
结果就是:
对上面的代码还可以修改为:
这样就可以形成两个流了,在处理器处理load指令的时候,可以完美的连接。
SIMD
只需要执行一条指令,实现多个相同的指令。
解决跳转
使用预测,如果预测失败,再恢复。
PS:slide from CMU 18-600. Click Here