realloc () для систем NUMA, использующих HWLOC - PullRequest
4 голосов
/ 04 августа 2011

У меня есть несколько пользовательских распределителей, которые предоставляют разные средства для выделения памяти на основе разных политик.Один из них выделяет память на определенном узле 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 без выделения новой памяти и перемещениястраниц вокруг?

Ответы [ 3 ]

2 голосов
/ 08 августа 2011

Чтобы ответить на изменения: в hwloc нет realloc, и в настоящее время мы не планируем добавлять его.Если вы заранее видите, что вы хотите (C-прототип функции), не стесняйтесь добавлять тикет в https://svn.open -mpi.org / trac / hwloc

Чтобы ответить на ogsx:Привязка памяти не специфична, она зависит от области виртуальной памяти и, возможно, от потока.Если вы перераспределяете, libc не делает ничего особенного.1) Если он может перераспределить внутри одной и той же страницы, вы получите память на том же узле.Хорошо, но редко, особенно для больших буферов.2) Если он перераспределяется на другой странице (в большинстве случаев для больших буферов), это зависит от того, была ли соответствующая страница уже выделена в физической памяти библиотекой malloc в прошлом (malloc'ed и освобождена в виртуальной памяти, новсе еще выделяется в физической памяти) 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)

Никогда не использовал это, новыглядит интересно.

1 голос
/ 04 августа 2011

Вы не правы.mbind может перемещать страницы, которые были затронуты.Вам просто нужно добавить MPOL_MF_MOVE.Вот что делает hwloc_set_area_membind_nodeset(), если вы добавляете флаг HWLOC_MEMBIND_MIGRATE.

move_pages - это просто другой способ сделать это (более гибкий, но немного медленнее, потому что вы можете перемещать независимые страницы в разные места).Оба mbind с MPOL_MF_MOVE и move_pages (и migrate_pages) заканчивают тем, что использовали точно такую ​​же функцию migrate_pages() в mm / migrate.c после того, как они преобразовали ввод в список страниц.

1 голос
/ 04 августа 2011

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 в наборе узлов.

Возвращает:

  • -1 с errno, установленным в ENOSYS, если действие не поддерживается
  • -1 с errno, установленным в EXDEV, если привязка не может быть принудительно установлена ​​

В Linux этот вызов реализован через mbind. Он работает только в том случае, если страницы в области не были затронуты, так что это просто более правильный способ перемещения области памяти во втором решении. ОБНОВЛЕНИЕ есть флаги MPOL_MF_MOVE * для перемещения затронутых данных.

Единственный известный мне системный вызов для перемещения страниц без перераспределения и копирования - move_pages

move_pages перемещает набор страниц в адресном пространстве исполняемого процесса на другой узел NUMA.

...