我目前正在研究优化应用程序的NUMA局部性。
到目前为止,我想我知道内存将驻留在分配后首次接触该NUMA节点上。
关于std::vector(使用默认分配器),我的问题是:
关于NUMA:
最佳答案
假设我们在谈论英特尔CPU:在它们的Nahlem老式CPU上,如果您有两个这样的CPU,则有一个开机选项来告诉他们如何在它们之间分配物理内存。物理体系结构是通过QPI连接的两个CPU,每个CPU控制自己的一组内存SIMM。选项是
对于第一种选择,如果您分配了一块内存,它将落到操作系统上,它将从物理地址空间中获取该内存,然后我想一个好的调度程序将努力运行线程以访问CPU上的该内存就是在控制它。对于第二个选项,如果您分配了几页内存,那么将在两个物理CPU之间分配内存,那么调度程序对访问它的线程所做的操作并不重要。我实际上只是短暂地玩了一下,无法真正发现差异。英特尔在QPI方面做得很好。我对较新的Intel体系结构不太熟悉,但是我假设它与以前的体系结构更多。
另一个问题实际上是NUMA节点是什么意思?如果我们指的是现代的Intel和AMD CPU,它们会向软件提供综合的SMP环境,并使用QPI/Hypertransport(以及现在的现代等效物)之类的东西在NUMA硬件体系结构之上。因此,在讨论NUMA本地性时,实际上是OS调度程序是否在控制线程访问的RAM的CPU上的内核上运行线程(SMP意味着它可以在任何内核上运行,并且仍然可以存取,尽管可能会有微小的延迟差异,但无论在物理内存中的分配位置如何,内存都可以访问)。我不知道答案,但我认为有些人会这样做。当然,我所做的将内核亲和力用于线程和内存的努力仅比让OS(Linux 2.6)做到这一点仅产生了微小的改进。而且,现代CPU上的缓存系统及其与CPU间互连(例如QPI)的交互非常聪明。
最早可追溯到SMP真正是纯硬件的OS,SMP不知道这样做。
小兔子洞-如果我们指的是纯NUMA系统(Transputers,PS3及其SPE中的Cell处理器),则线程将在特定内核上运行,并且只能访问该内核的内存;为了访问(通过另一个线程)在另一个内核的内存中分配的数据,该软件必须通过在某些互连上发送数据来对自身进行分类。除非学习,否则很难编写代码,但是结果可能会很快。英特尔花了大约10年的时间才能将Cell处理器与原始处理器相提并论。
关于c++ - std::vector保留并调整NUMA位置的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63605800/