在这个应用程序中,我有N(POSIX)线程组。第一组启动,创建一个对象A,然后关闭。稍后,一个有N个线程的新组启动,使用A创建一个类似的对象B,然后关闭。重复这种模式。该应用程序是高度内存密集型的(A和B具有大量malloc的阵列)。我希望本地访问内存尽可能多。我可以使用numactl --localalloc
来实现这一点,但为了实现这一点,我还需要确保来自第一组和第二组的那些处理相同数据的线程绑定到同一个NUMA节点。我调查了sched_setaffinity
,但想知道是否存在更好的方法。
应用程序的逻辑使得没有单独的线程组的解决方案会破坏程序逻辑。也就是说,一组线程管理第一个对象A和后来的对象B(没有在其间卷入)的解决方案将是非常人为的,并且会消除代码的面向对象布局。
答案 0 :(得分:1)
将B组中的线程绑定到它们在A组上运行的相同核心比您需要的更严格。现代处理器每个核心使用专用的1级高速缓存(L1)和2级高速缓存(L2),因此将线程绑定到特定核心只有获取那些仍然在这些高速缓存中“热”的数据才有意义。您可能的意思是将B组线程绑定到与组A中的线程相同的numa节点,以便大型数组位于同一本地内存中。
那就是说,你有两个选择:
选项(1)相对容易,所以我们来谈谈如何实现选项(2)。
以下SO答案描述了如何在给定进程中的虚拟地址的情况下找出哪个numa节点具有本地内存:
Can I get the NUMA node from a pointer address (in C on Linux)?
-lnuma中有一个move_pages函数:http://linux.die.net/man/2/move_pages可以将当前的地址状态(页面)报告给节点映射:
节点也可以是NULL,在这种情况下,move_pages()不会移动任何页面,而是返回状态数组中每个页面当前所在的节点。可能需要获取每个页面的状态以确定需要移动的页面。
有了这些信息,你想设置你的B组线程与该numa节点的亲和力,为什么我们去这个SO答案
How to ensure that std::thread are created in multi core?
对于带POSIX线程的GNU / linux,你需要在FreeBSD cpuset_setaffinity(),Windows SetThreadAffinityMask()等中使用pthread_setaffinity_np()。