例如,在具有2个四核处理器的双插槽系统中,线程调度程序是否尝试将线程保留在同一处理器中的相同进程中?因为在进程中的线程具有大量共享内存访问的情况下,在不同处理器中交错不同进程的线程会降低性能。
答案 0 :(得分:3)
取决于。
在当前的英特尔平台上,BIOS默认似乎是内存在系统中的套接字之间逐页交错。分配1Mbyte和一半将在一个插槽上,一半在另一个插槽上。这意味着无论您的线程在哪里,它们都可以同等地访问数据。
这使操作系统非常简单 - 任何地方都可以。
这可能会对你不利。呈现给OS的SMP硬件环境由通过QPI协作的CPU合成。如果有很多线程都访问相同的数据,那么这些链接可能会变得非常繁忙。如果它们太忙,则会限制性能,并且您受I / O限制。我就是这样;采用英特尔内存子系统设计的Z80内核与我实际获得的内核芯片一样快(好吧,我可能会夸大......)。
在一天结束时,真正的问题是内存不够快。英特尔和AMD最近都对内存做了一些令人印象深刻的事情,但我们仍然因其缓慢而受到阻碍。理想情况下,内存足够快,以便所有内核都具有时钟速率访问时间。 Cell处理器就是这样做的 - 每个SPE都有一些SRAM而不是缓存,一旦你绕过它们就可以让它们真正唱歌。
=== EDIT ===
还有更多内容。正如Basile Starynkevitch暗示,另一种方法是接受NUMA。
NUMA是现代CPU实际体现的内容,内存访问不均匀,因为其他CPU插槽上的内存无法通过寻址总线直接访问。相反,CPU通过QPI链接(或AMD的Hypertransport)请求数据,要求其他CPU从其内存中取出数据并将其发回。因为CPU在硬件中为您完成所有这些操作,所以它最终看起来像传统的SMP环境。 QPI / Hypertransport非常快,所以大多数时候它足够快。
如果您编写代码以反映硬件的体系结构,理论上可以进行改进。因此,这可能涉及(例如)在系统中有两个数据副本,每个插槽上有一个副本。 Linux中的内存关联例程专门用于分配内存,而不是跨所有套接字交错。还有CPU关联例程,允许您控制一个线程正在运行的CPU核心,这个想法是您在一个接近它将处理的数据缓冲区的核心上运行它。
好的,这可能意味着对源代码进行了大量投资,以使其适合您(特别是如果数据重复与程序的流程不相符),但是如果QPI成为一个有问题的瓶颈这是你唯一能做的事情。
我在某种程度上摆弄了这个。在某种程度上,这是一个正确的faff。英特尔和AMD(以及操作系统和库)的整体思维方式是为您提供一个SMP环境,在大多数情况下,它是非常好的。但是,它们允许您使用NUMA来加载必须调用的库函数,以获得所需的线程和内存部署。
然而,对于你想要一点点额外速度的边缘情况,如果架构和操作系统是严格的NUMA,则根本没有SMP。就像Cell处理器一样。更容易,不是因为它写起来很简单(实际上它会更难),但是如果你完全运行它,那么你肯定知道它的速度和硬件可能达到的速度一样快。有了我们现在所拥有的伪造的SMP,你可以尝试使用NUMA,但是你大部分都想知道它是否尽可能快。它不像图书馆告诉你,你正在访问实际驻留在另一个套接字上的内存,他们只是让你这样做而没有暗示还有改进的余地。