内存控制器将CPU发送的内存读写请求调度分发至内存芯片上,包括事务调度(Transaction Scheduling)、地址转换(Address Translation)、命令调度(Command Scheduling)、信号时序管理等步骤,如图2.20所示。除了正常的外部DRAM读写请求之外,DRAM内存控制器还需要管理刷新操作。
图2.20 DRAM内存控制器结构 [1]
内存控制器既可以部署在内存条内,也可以在CPU里。在内存条内部署内存控制器,可以支持不同的内存介质特性,而且可以降低CPU芯片的能耗,但其缺点是访问延迟相对较高,而且由于主机端的语义信息缺失,多核之间的内存访问请求调度的信息较少,从而影响内存带宽的性能。在CPU里部署内存控制器,与在内存条内部署内存控制器的方式相比,优缺点相反。
在内存控制器里,内存请求的调度是影响内存性能的一个重要因素。内存请求调度与所有调度策略有着类似的目标:提高吞吐率、降低延迟和保证公平。与其他调度不同的是需要考虑内存的特性,具体需要考虑的因素包括请求的行缓存命中或缺失状态、请求到达先后顺序、请求的类别(预取请求/读请求/写请求)、请求优先级等。
其中,请求的行缓存命中或缺失状态是内存调度中需要考虑的比较独特的因素。在DRAM内存中,行缓存管理有两种基本策略:开放行(Open Row)和关闭行(Closed Row)。
在开放行策略中,访问某一内存行之后,数据保留在行缓存中,不需要回写(即预充电)到内存行中。在这种策略下,如果下一个请求访问同一内存行,则行缓存命中,这样节省了回写的开销。如果下一个请求访问不同的行,则行缓存缺失,需要先进行回写,然后激活新的行,最后进行数据访问操作,延迟相对较高。
在关闭行策略中,每次内存访问之后,所访问的内存行的数据由行缓存回写到原有内存行中。在这种策略下,如果下一个请求访问同一内存行,则仍然需要先激活该内存行,然后读,最后回写,造成了较高的延迟。如果下一个请求访问不同行,则需要先激活该内存行,然后读,最后回写,与开放行策略相比避免了关键路径上的回写开销。