функция malloc/memcpy работает независимо от NUMA?

Пытаясь увеличить скорость моих приложений на не-NUMA/стандартных ПК, я всегда обнаруживал, что узким местом был вызов malloc(), потому что даже на многоядерных машинах он используется/синхронизируется между всеми ядрами.

У меня есть ПК с архитектурой NUMA, использующий Linux и C, и у меня есть два вопроса:

  1. В машине NUMA, поскольку каждое ядро ​​снабжено собственной памятью, будет ли malloc() выполняться независимо на каждом ядре/памяти, не блокируя другие ядра?
  2. Как в этих архитектурах выполняются вызовы memcpy()? Можно ли это вызывать независимо на каждом ядре или вызов одного ядра заблокирует остальные? Возможно, я ошибаюсь, но я помню, что у memcpy() была такая же проблема, как и у malloc(), т.е. когда одно ядро ​​​​использует его, другим приходится ждать.

person Abruzzo Forte e Gentile    schedule 29.03.2011    source источник


Ответы (2)


Машина NUMA — это система с общей памятью, поэтому доступ к памяти с любого процессора может достигать памяти без блокировки. Если бы модель памяти была основана на сообщениях, то доступ к удаленной памяти потребовал бы от исполняющего процессора запроса на выполнение желаемой операции локальным процессором. Однако в системе NUMA удаленный процессор может по-прежнему влиять на производительность близкого процессора из-за использования каналов памяти, хотя это может зависеть от конкретной архитектурной конфигурации.

Что касается 1, это полностью зависит от ОС и библиотеки malloc. ОС отвечает за представление памяти для каждого ядра/процессора либо как единое пространство, либо как NUMA. Malloc может быть или не быть осведомленным о NUMA. Но, по сути, реализация malloc может или не может выполняться одновременно с другими запросами. И ответ от Ала (и связанное с ним обсуждение) рассматривает этот момент более подробно.

Что касается 2, поскольку memcpy состоит из серии загрузок и хранилищ, единственным влиянием снова будут потенциальные архитектурные эффекты использования контроллеров памяти других процессоров и т. д.

person Brian    schedule 29.03.2011
comment
Привет Брайан. Большое спасибо. Знаете ли вы какую-нибудь хорошую библиотеку malloc, поддерживающую NUMA? Я погуглил и нашел MPC... на ваш взгляд, это хорошо? - person Abruzzo Forte e Gentile; 29.03.2011
comment
В редких случаях, когда я пишу что-то, поддерживающее NUMA, я напрямую выделяю свою память из ОС, используя VirtualAllocExNuma (Windows) или libnuma (linux). - person Brian; 30.03.2011
comment
Большое спасибо, я попробую. - person Abruzzo Forte e Gentile; 30.03.2011

  1. Вызовы malloc в отдельных процессах будут выполняться независимо, независимо от того, используете ли вы архитектуру NUMA. Вызовы malloc в разных потоках одного и того же процесса не могут выполняться независимо, поскольку возвращаемая память одинаково доступна для всех потоков внутри процесса. Если вам нужна память, которая является локальной для определенного потока, прочитайте Локальное хранилище потоков. Мне не удалось найти четкой документации о том, могут ли виртуальная машина Linux и планировщик оптимизировать соответствие между ядрами, потоками, локальной памятью и локальным хранилищем потоков.
person Al Riddoch    schedule 29.03.2011
comment
Вызовы malloc в разных потоках одного и того же процесса не могут выполняться независимо — на не-NUMA они могут с пулами памяти для каждого потока, хотя тогда вызовы free в разных потоках могут быть не независимыми, поскольку, конечно, вы можете освободить память в другом поток, из которого вы его выделили. - person Steve Jessop; 29.03.2011
comment
Но это полностью зависит от реализации malloc. Люди обычно используют сторонние библиотеки malloc (например, tcmalloc) для повышения производительности в многопоточных приложениях (хотя ни tcmalloc, ни glibc malloc не учитывают NUMA). - person nos; 29.03.2011
comment
Привет, Стив. Насколько я знаю, пулы памяти - это просто постоянно предварительно выделенные куски памяти, которые никогда не освобождаются (по крайней мере, так я использовал в архитектуре, отличной от NUMA). Мне кажется, что то, что вы предлагаете, - это скорее решение, основанное на том, что какая-то библиотека выполняет две вещи: A = создание пула памяти для каждого потока B = переопределение поведения malloc. Я прав или это что-то действительно указано на уровне ОС для такого оборудования? - person Abruzzo Forte e Gentile; 29.03.2011
comment
@Abruzzo: я думаю, что пул используется в разных контекстах для разных целей. Пул не обязательно означает что-то там, где нет средств для освобождения отдельного распределения, и да, я действительно имею в виду, что malloc реализации могут это сделать. Я добавил комментарий, потому что не был уверен, говорил ли Ал об архитектуре NUMA или не-NUMA (или о обеих) в этом предложении, и я просто хотел добавить, что это зависит от реализации, откуда на самом деле берется malloc память, и обычно Linux позволяет вам выбрать распределитель, который позволяет избежать большинства конфликтов на malloc. - person Steve Jessop; 30.03.2011
comment
p.s. Я также нашел libnuma и TCMalloc, но они кажутся недостаточно хорошими (по крайней мере, TCMalloc кажется хорошим только для не-NUMA). - person Abruzzo Forte e Gentile; 30.03.2011