4

我有几个自定义分配器,它们提供了基于不同策略分配内存的不同方法。其中之一在定义的 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 仅提供分配和释放内存的方法,我想知道我应该如何实现reallocate()

两种可能的解决方案:

  1. 分配新的内存区域和memcpy()数据
  2. 用于hwloc_set_membind_nodeset()设置节点集的内存分配/绑定策略,使用普通malloc()/posix_memalign()realloc().

任何人都可以帮助我解决这个问题吗?

更新:

我试图使问题更具体:是否有可能在不分配新内存和移动页面的情况下执行realloc()使用?hwloc

4

3 回答 3

2

回复编辑: hwloc 中没有 realloc,我们目前没有计划添加一个。如果您准确地看到了您想要的(函数的 C 原型),请随时向https://svn.open-mpi.org/trac/hwloc添加票证

回复 ogsx:内存绑定不是特定的,它是特定于虚拟内存区域的,并且可能是特定于线程的。如果你重新分配,libc 不会做任何特别的事情。1)如果它可以在同一页面内重新分配,您将在同一节点上获得内存。很好,但很少见,尤其是对于大缓冲区。2)如果它重新分配在不同的页面中(大多数情况下是大缓冲区),这取决于过去 malloc lib 是否已经在物理内存中分配了相应的页面(在虚拟内存中分配和释放,但是仍然分配在物理内存中) 2.a)如果已经分配了虚拟页面,那么过去可能由于各种原因在另一个节点上分配了它,你就完蛋了。2.b) 如果新的虚拟页面还没有分配,默认分配在当前节点上。如果您之前使用 set_area_membind() 或 mbind() 指定了绑定,它将在正确的节点上分配。在这种情况下,您可能会很高兴。

简而言之,这取决于很多事情。如果您不想打扰 malloc 库做复杂/隐藏的内部事情,特别是如果您的缓冲区很大,那么使用 mmap(MAP_ANONYMOUS) 而不是 malloc 是确保在您真正需要时分配页面的简单方法他们。你甚至可以让 mremap 做一些类似于 realloc 的事情。

alloc 变为 mmap(length) + set_area_membind realloc 变为 mremap + set_area_membind(在整个 mremap'ed 缓冲区上)

从未使用过,但看起来很有趣。

于 2011-08-08T07:10:17.260 回答
1

你错了。mbind 可以移动被触摸的页面。您只需要添加 MPOL_MF_MOVE。hwloc_set_area_membind_nodeset()如果你添加 flag就是这样HWLOC_MEMBIND_MIGRATE

move_pages只是一种不同的方法(更灵活但有点慢,因为您可以将独立页面移动到不同的位置)。一旦将输入转换为页面列表,mbind withMPOL_MF_MOVE和 move_pages(和 migrate_pages)最终都会使用 mm/migrate.c 中完全相同的函数。migrate_pages()

于 2011-08-04T12:18:21.950 回答
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) 标识的已分配内存绑定到 nodeset 中的 NUMA 节点。

回报:

  • 如果不支持该操作,则 -1 将 errno 设置为 ENOSYS
  • 如果绑定无法强制执行,则 -1 将 errno 设置为 EXDEV

在 linux 上,此调用是通过mbind 它仅在该区域中的页面未被触及时才起作用,因此在您的第二个解决方案中移动内存区域是更正确的方法。更新有一个 MPOL_MF_MOVE* 标志来移动触摸的数据。

我知道的唯一一个无需重新分配和复制即可移动页面的系统调用是move_pages

move_pages 将已执行进程的地址空间中的一组页面移动到不同的 NUMA 节点。

于 2011-08-04T09:13:55.463 回答