答案 0 :(得分:0)
这是我通过 DuckDuckGo 找到的一篇很好的小论文,它很好地解释了 TLB 的工作原理(从外观上看是威斯康星大学麦迪逊分校 Comp Sci 课程的一部分):https://pages.cs.wisc.edu/~remzi/OSTEP/vm-tlbs.pdf。这应该足以让您开始推理您的数据布局和算法可能如何影响您的 TLB 命中率。
本质上,它归结为在内存中保持事物紧密相连,因此您可以最大限度地减少访问数据和指令时必须访问的不同页面的数量。以 4K 或更大的页面为典型,结果证明大多数程序通常具有非常高的 TLB 命中率。事实上,我们今天使用的计算机系统是专门设计这种方式的,这是基于对大多数计算工作负载在设计这些系统之前通常会做什么的广泛研究。
如果您考虑一个没有任何分支运行的函数,您可以想象每条指令的顺序获取和执行,从页面中的某个点开始并继续向下。第一条指令可能会导致 TLB 未命中,但之后的每条指令都将是 TLB 命中,直到到达页面末尾。当访问下一页的第一条指令时,可能会有另一个 TLB 未命中,但随后该页指令的其余部分将全部命中。如果函数包含循环,效果会更好,因为 CPU 会跳回到它刚刚执行的地方。它甚至可能很长时间都不会离开同一个页面。
程序还倾向于访问他们最近访问过的页面上的数据。例如,一个函数内的所有自动变量通常都驻留在一个或两个堆栈页面上,并且在许多情况下,调用堆栈中所有函数的所有堆栈帧通常都适合少量页面。对于堆分配或静态分配的内存,通常也有一些局部性。我上面提到的论文给出了一个很好的例子,说明数组遍历如何导致高 TLB 命中率。
往往具有相对较低 TLB 命中率的工作负载是那些将频繁访问的数据和/或指令分布在大量页面上的工作负载,其间包含不常访问的数据/指令;以及那些使他们的 TLB 条目无效的人(例如,在某些系统上,进程上下文切换会导致 TLB 被转储)。