我有几个自定义分配器,它们提供了不同的方法来根据不同的策略分配内存。其中一个在定义的NUMA节点上分配内存。分配器的接口是直接的
template<typename config>
class NumaNodeStrategy
{
public:
static void *allocate(const size_t sz){}
static void *reallocate(void *old, size_t sz, size_t old_sz){}
static void deallocate(void *p, size_t sz){}
};
使用hwloc_alloc_membind_nodeset()
方法处理分配本身,并为分配策略设置相应的参数等。但是,hwloc只提供分配和释放内存的方法,我想知道应该如何实现{{1 }}
两种可能的解决方案:
reallocate()
数据memcpy()
设置节点集的内存分配/绑定策略,并使用纯hwloc_set_membind_nodeset()
/ malloc()
和posix_memalign()
。任何人都可以帮助我做到这一点吗?
更新
我尝试更具体地提出问题:是否有可能使用realloc()
执行realloc()
而无需分配新内存并移动页面?
答案 0 :(得分:2)
回复编辑: hwloc中没有realloc,我们目前没有计划添加一个。如果你看到了你想要的东西(函数的C原型),可以随意添加一张票给https://svn.open-mpi.org/trac/hwloc
回复ogsx:内存绑定不是特定的,它是特定的虚拟内存区域,可能是特定于线程的。如果你重新分配,libc没有做任何特别的事情。 1)如果它可以在同一页面内重新分配,则会在同一节点上获得内存。好,但很少见,特别是对于大缓冲区。 2)如果它在一个不同的页面重新分配(大多数情况下是大缓冲区),它取决于过去的malloc lib是否已经在物理内存中分配了相应的页面(malloc'ed并在虚拟内存中释放,但是仍然在物理内存中分配) 2.a)如果已经分配了虚拟页面,它可能由于各种原因在过去分配到另一个节点上,你就搞砸了。 2.b)如果尚未分配新虚拟页面,则默认为在当前节点上分配。如果您之前使用set_area_membind()或mbind()指定了绑定,则它将在右侧节点上分配。在这种情况下你可能会很开心。
简而言之,这取决于很多事情。如果您不想使用malloc lib来执行复杂/隐藏的内部事务,特别是如果您的缓冲区很大,那么执行mmap(MAP_ANONYMOUS)而不是malloc是确保在您真正需要时分配页面的简单方法他们。你甚至可以使用mremap来做类似于realloc的事情。
alloc变为mmap(length)+ set_area_membind realloc变为mremap + set_area_membind(在整个mremap的缓冲区上)
从未使用过,但看起来很有趣。
答案 1 :(得分:1)
hwloc_set_area_membind_nodeset可以解决问题,不是吗?
HWLOC_DECLSPEC int
hwloc_set_area_membind_nodeset (hwloc_topology_t topology,
const void *addr, size_t len, hwloc_const_nodeset_t nodeset,
hwloc_membind_policy_t policy, int flags)
将(addr,len)标识的已分配内存绑定到节点集中的NUMA节点。
返回:
在linux上,此调用是通过mbind
实现的。只有在未触摸区域中的页面时才有效,因此在第二个解决方案中移动内存区域的方法更为正确。 UPDATE 有一个MPOL_MF_MOVE *标记来移动触摸的数据。
唯一没有重新分配和复制的移动页面的系统调用我知道move_pages
move_pages将已执行进程的地址空间中的一组页面移动到另一个NUMA节点。
答案 2 :(得分:1)
你错了。 mbind可以移动已被触摸的页面。您只需添加MPOL_MF_MOVE即可。这就是hwloc_set_area_membind_nodeset()
添加标记HWLOC_MEMBIND_MIGRATE
时的作用。
move_pages
只是一种不同的方式(更灵活,但有点慢,因为你可以将独立的页面移动到不同的地方)。一旦将输入转换为页面列表,mbind MPOL_MF_MOVE
和move_pages(以及migrate_pages)最终都会使用mm / migrate.c中完全相同的migrate_pages()
函数。