Data Fetching中的多核干扰
在基于强化学习的数据预取中,多核之间的相互干扰是目前急需解决的难题,如何解决多核之间的资源分配是目前比较热门的方向。这篇Blog主要叙述一下分配的资源都有哪些,它们又是如何被干扰的。总而言之,预取带来的收益,必须大于它消耗的共享资源。
LLC缓存干扰
很明显在数据预取的时候,肯定会占用cache缓存。对于多核而言,LLC共用缓存显然是大家需要抢占的资源。如果有一个核心疯狂把数据拉进LLC,显然会将其他核心的cache line挤了出去,结果导致:
- 其它核心的命中率下降
- 更多访问走到内存,严重降低效率
DRAM带宽干扰
如果一个核预取很多无用或过早的数据,它会占掉 DRAM 带宽、片上总线带宽、内存控制器队列项。这样另一个核的真实 demand miss(真正需要的数据)就可能被拖慢。其实和LLC干扰有些类似。
也就是说,预取本来是为了“隐藏延迟”,但在多核下可能变成:
- 自己核的预取请求
- 挤占别的核的 demand 请求
- 让整体吞吐下降
抢 MSHR / Fill Buffer / 请求队列
除了缓存容量和带宽,还会争抢很多内部硬件表项,比如:
- MSHR(miss status holding registers)
- fill buffer
- cache miss queue
- memory controller request queue
这些资源数量都有限。 一个核如果预取很多流,会把这些表项占满,导致另一个核即使发生真正的 cache miss,也没法及时发出去,形成head-of-line blocking 或队列拥塞。
增加一致性流量
如果预取的是共享数据,甚至是会被多个核读写的数据,还可能引发额外的一致性活动。
例如:
一个核预取到某个 cache line
另一个核很快写这个 line
预取进来的副本马上失效
产生额外 snoop / invalidate / coherence traffic
如果程序本来就有false sharing(伪共享),预取器可能把这种无效流量进一步放大。
影响内存调度公平性
多个核一起跑时,内存控制器通常要在不同请求流之间调度。预取请求如果太多,会改变控制器看到的请求分布,可能出现:
某些核更容易“占住”队列
行缓冲命中模式被改变
某个应用延迟被拉高
系统公平性变差
所以在服务器/多程序负载中,经常会看到:单核测得很有效的预取策略,一到多核就收益下降甚至变负。