我知道在单核机器上,多线程编程会增加缓存未命中,因为每个线程都有自己的堆栈和自己的指令指针等。因此,当多线程进行上下文切换时,CPU 必须重新加载另一段 RAM,这将给我们带来缓存未命中。
所以我在想多核是否可以避免这个问题?假设我有一个包含两个线程的程序,我的机器有两个内核。如果每个线程都可以分配给不同的内核,这是否意味着我可以避免缓存未命中问题?
答案一如既往,这取决于。
假设单独的内核带有单独的 L1 缓存(不能保证,但足够常见(,那么是的,缓存未命中会更少。但这确实取决于每个线程"一次性"处理了多少数据,以及在需要获取新数据之前对其进行了多少处理。如果这比不同内核上的缓存更多,则两者的缓存将提升到(至少在英特尔 CPU 上(共享的 L3 缓存。然后,L3 缓存成为瓶颈。如果数据溢出,那么它就会回到SDRAM,这就像它得到的那样慢。如果数据集大于系统的RAM,那么这就是操作系统页面文件的用途,而且速度非常慢。
CPU设计人员通常认为,他们选择的缓存架构将满足广泛的"典型"应用程序,他们在这方面非常成功。但是,如果你真的想要最后百分之一的性能,缓存引擎的"聪明"可能会开始对程序员不利。缓存可能猜测你的程序接下来要访问数据X,但实际上它要求数据Y.缓存未命中,速度变慢。确切地了解芯片上的缓存架构在任何特定情况下将做什么可能很难知道,甚至在编写代码时也很难适应。
一些缓存允许程序员给出提示 - PowerPC 7400 系列可以做到这一点,而且非常有用。程序不依赖于缓存引擎的猜测,而是可以明确地告诉缓存,如果可以的话,缓存开始加载数据Y是非常值得的。没有缓存未命中。如果程序员足够聪明,知道他们可以给出比缓存猜测更好的提示,那么程序员只需要在程序的正确点包含相关指令。
IBM(想想:索尼Playstation 3(的Cell处理器将这一点发挥到了极致。根本没有缓存。相反,片上每个数学内核都有 256k 的 RAM,具有单周期访问(因此,就像 L1 缓存一样(。完全由程序员从片外RAM将数据和代码加载到RAM中。编程非常困难,但一旦掌握,它就非常非常快。