Отвязка vNuma от количества ядер в vSphere 6.5

Данная статья является переводом англоязычной статьи Френка Деннемана, которая показалась мне достаточно интересной.

В vSphere 6.5 были сделаны изменения, касающиеся определения размеров виртуальной топологии NUMA для виртуальной машины.

Понимание принципов построения vNUMA имеет важное значение для построения правильно работающей инфраструктуры. Данная статья предназначена для тех, кто использует виртуальные машины (ВМ) с нестандартным количеством ядер на сокет (отличным от 1), и планирует мигрировать на vSphere 6.5. Возможно, вы захотите изменить Advanced Setting на ваших хостах 6.5 — информация об этом находится в конце статьи.

Давайте начнем с понимания того, как влияет количество виртуальных ядер в сокете на vNUMA.

vCPU — это виртуальный процессор, содержащий одно ядро и занимающий один сокет. Настройка Cores per Socket задает количество ядер, по умолчанию она равна 1. При добавлении дополнительных vCPU к ВМ, увеличивается количество сокетов.

Начиная с vSphere 5.0, VMkernel «показывает» для ВМ vNUMA (виртуальную топологию NUMA), позволяя повысить производительность гостевых ОС и приложений, совместимых с NUMA.

vNUMA «прокидывается» внутрь ВМ при выполнении двух условий:

  1. ВМ содержит 9 или более vCPU;
  2. количество vCPU превышает количество ядер* одного физического NUMA-узла.

*есть Advanced Settings «numa.vcpu.preferHT=TRUE», указывающая что в качестве количества ядер нужно считать количество потоков HyperThreading (превышающее количество ядер вдвое).

Давайте исследуем vNUMA-конфигурацию ВМ на хосте:

vmdumper -l | cut -d \/ -f 2-5 | while read path; do egrep -oi «DICT.*(displayname.*|numa.*|cores.*|vcpu.*|memsize.*|affinity.*)= .*|numa:.*|numaHost:.*» «/$path/vmware.log»; echo -e; done

При использовании этой команды на 10vCPU ВМ и хосте vSphere 6.0 с двумя процессорами E5-2630 мы увидим:

vnuma01В нашей ВМ 10 vCPU. «cpuid.coresPerSocket = 1» означает, что она настроена с одним ядром на сокет. Нижняя строка (numaHost:) обобщает vNUMA для ВМ. Виртуальные узлы и физические домены будут рассмотрены ниже.

Все 10 vCPU расположены на одном физическом домене, что означает их выполнение на одном физическом ЦП (сокете или NUMA-узле). Для соответствия этой физической архитектуре в vNUMA присутствует один виртуальный NUMA-узел.

Утилита CoreInfo (MS Sysinternals) отображает архитектуру vCPU в ВМ с большей детализацией (в Linux также можно использовать команды numactl —hardware и lstopo -s). Утилита отображает каждый сокет, каждый логический процессор и карту кэш. Запомните, как выглядит кэш-карта, когда мы будем рассматривать многоядерные vCPU.

vnuma02

Теперь увеличим количество vCPU до 16, превысив количество ядер одного физического NUMA-узла.

numa03Coreinfo использует звездочку для отображения привязки логического процессора к сокету и NUMA-узлу. В этой конфигурации первые 8 vCPU (0-7) располагаются на NUMA0, а вторые 8 vCPU — на NUMA1.

vmdumper показывает следующую информацию:

numa04Для ВМ с 10 vCPU подходящее значение параметра numa.autosize.vcpu.maxPerVirtualNode=10. Для 16vCPU — numa.autosize.vcpu.maxPerVirtualNode=8.

Как вы видите, VMkernel пытается разместить vCPU на минимальном количестве виртуальных NUMA-узлов. Сейчас мы покажем, почему не стоит делать vCPU с несколькими ядрами (например, с 8ю).

Топология vNUMA состоит из VPD (Virtual Proximity Domain или виртуальный домен родства) и PPD (Physical Proximity Domain  или физический домен родства). VPD виден из виртуальной машины, PPD — это физические NUMA-узлы.

Каждый PPD соответствует отдельному сокету.

numa05

Для понимания PD представьте себе группу привязки ВМ к группе хостов. Но в данном случае мы привязываем vCPU к сокету (и его ядрам).

VPD — отображает vNUMA для виртуальной машины. Количество VPD зависит от числа vCPU и физического количества ядер (или настройки «количество ядер на сокет» в ВМ). vSphere пытается выравнивать VPD вместе с PPD. Например, если мы создали 16vCPU ВМ на «эталонном» хосте, то будет организовано два PPD. В рамках этих PPD будут развернуты VPD. Каждый VPD будет загружать по 8 физических ядер из одного PPD.

numa06

Если настройка «количество ядер на сокет» не изменено, то каждый vCPU назначается на свой виртуальный сокет. На рисунке виртуальные сокеты (черные) и vCPU (голубые) расположены над VPD.

Но эта красота может быть испорчена, если вы измените настройку количества ядер.

В этом случае VPD даже могут располагаться на нескольких PPD, если количество виртуальных ядер будет превышать количество физических ядер.

Представьте себе ВМ с 40 vCPU и 20 ядрами на сокет, расположенная на хосте с 4 процессорами по 10 ядер в каждом. Такая машина создаст 2 VPD, но они будут расположены на 4 PPD.

numa07

Как видите, эта настройка может привести к тому, что будет использоваться неоптимальная конфигурация.

В результате такого распределения VPD по нескольким PPD оптимизация процессорных инструкций становится практически бесполезной.

Так что, если вы меняете эту настройку, крайне не рекомендуется превышение количества виртуальных ядер над количеством физических!

 

В ESXi 6.5 планировщик претерпел несколько интересных изменений. Одно из этих изменений — возможная оптимизация vNUMA за счет того, что количество виртуальных сокетов больше не равно количеству vNUMA узлов.

Смотрите, до версии ESXi 6.5 если у вас есть ВМ с 16vCPU и 2 ядра на сокет, то создавались 8 PPD и 8 VPD.

numa08

Проблема этой конфигурации в том, что vNUMA абсолютно не соответствовала NUMA.

numa09

Гостевая ОС видит 16 ЦП, распределенных по своему сокету. Каждая пара ЦП имеет собственный кэш и локальную память. ОС считает память других ЦП (сокетов) «удаленной». В результате, ОС необходимо побить память на 8 кусков и оптимизировать использование кэша и памяти, основываясь на том, что отображается vNUMA. Для подобной 16-процессорной ВМ, расположенной на 2хпроцессорном хосте это выглядело бы так:

numa10

Ну и вывод CoreInfo:

numa11

Вот для избежания «фрагментации» локальной памяти и было изменено поведение по созданию VPD в 6.5. В новой версии vSphere размер VPD зависит от количества физических ядер в сокете. В результате, vNUMA старается быть максимально похожей на NUMA.

Точно такая же 16-процессорная ВМ (2 ядра на сокет) на двухпроцессорном сервере с Intel Xeon E5-2630 v4  (10 ядер на процессор) в vmdumper покажет следующее (vSphere 6.5):

numa12

Так как есть только два физических NUMA-узла, то и создается только два PPD и VPD. Разные виртуальные сокеты располагаются на одном VPD.

numa13

В настройках хоста появилась дополнительная опция “NUMA config: consolidation =1”, регулирующая это поведение (минимизировать количество PD).

В данном случае будет создано два VPD, каждый со своим адресным пространством.

numa14

ВМ с ОС Windows 2012 определит два NUMA-узла:

numa15

CoreInfo — смотрим вниз:

numa16

Как вы видите, новая оптимизация лучше помогает располагать виртуальные процессоры и vNUMA относительно физической топологии, чтобы оптимизировать доступ к памяти.

Современные ОС и приложения умеют оптимизировать расположение данных в памяти и кэше.

Тем не менее, большинство приложений (даже оптимизированных по Symmetric Multi-Processing) не умеют балансировать нагрузку между NUMA-узлами. Современные ОС используют политику, при которой приложение получает память, но ее виртуальный адрес не привязывается к физическому адресу. При доступе приложения к памяти ОС определяет «локальную» ОЗУ и размещает эту память туда.

В идеальном мире поток, который создал память, продолжает с ней работать. В реальном же многие приложения создают память одним потоком, а получают доступ к ней через другие.

Поэтому лучшей рекомендацией является не изменять настройку «количество ядер в сокете». Если же по каким-то причинам вам необходимо это сделать (лицензионные и т.д.), то обязательно учитывайте количество физических ядер.

Единственная проблема тут с виртуальным сокетом. Все ядра виртуального сокета расшаривают общий L3 кэш.

numa17

ВНИМАНИЕ/АХТУНГ/АЛЯРМА!!!!!!111111

К сожалению, некоторые топологии vNUMA не были должным образом протестированы на предмет их миграции с предыдущей версии vSphere. Увы, это может привести к PSOD вашего хоста ESXi 6.5.

Если у вас есть такие ВМ (с настройкой «ядра на сокет» отличной от 1) или вы задавали параметр «numa.autosize.once» = False, то рекомендуется изменить следующий параметр:

«Numa.FollowCoresPerSocket» = 1

Перезагрузка хоста не требуется. Эта настройка «учит» ESXi 6.5 создавать vNUMA так же, как это было в 6.0 (настройка «ядра на сокет» задает размер VPD).

VMware уже столкнулась с несколькими обращениями. Поэтому проверьте эту ситуацию в тестовой среде и, при необходимости, укажите эту настройку.

Также вы можете почитать kb2147958. VMware работает над фиксом.

Запись опубликована в рубрике 6.0, 6.5, VMware, vSphere. Добавьте в закладки постоянную ссылку.

5 комментариев: Отвязка vNuma от количества ядер в vSphere 6.5

  1. Сергей говорит:

    Есть хост с двумя процессорами по 12 ядер всего 24 ядра, если включить HT то получится 48 ядер
    как правильно задать количество ядер для VM c 24 ядрами

  2. A.Vakhitov говорит:

    Смотрите на приложение. Если это SQL, лучше 2*12.
    Если в приложении про Numa не слова (и нет ограничения по количеству CPU), лучше 24*1.

  3. Сергей говорит:

    да это sql будет VM на весь хост пример для двух 8 процесоров
    то есть устанавливаем CPU 16
    Cores per Socket 8
    Socket у нас получается 2

    DICT numvcpus = «16»
    DICT memSize = «92000»
    DICT displayName = «srv-mssql01»
    DICT numa.autosize.vcpu.maxPerVirtualNode = «4»
    DICT numa.autosize.cookie = «40001»
    DICT cpuid.coresPerSocket = «8»
    numaHost: NUMA config: consolidation= 1 preferHT= 1
    NUMA: VM is wider than host.
    numa: coresPerSocket= 8 maxVcpusPerVPD= 4
    numaHost: 16 VCPUs 4 VPDs 4 PPDs
    numaHost: VCPU 0 VPD 0 PPD 0
    numaHost: VCPU 1 VPD 0 PPD 0
    numaHost: VCPU 2 VPD 0 PPD 0
    numaHost: VCPU 3 VPD 0 PPD 0
    numaHost: VCPU 4 VPD 1 PPD 1
    numaHost: VCPU 5 VPD 1 PPD 1
    numaHost: VCPU 6 VPD 1 PPD 1
    numaHost: VCPU 7 VPD 1 PPD 1
    numaHost: VCPU 8 VPD 2 PPD 2
    numaHost: VCPU 9 VPD 2 PPD 2
    numaHost: VCPU 10 VPD 2 PPD 2
    numaHost: VCPU 11 VPD 2 PPD 2
    numaHost: VCPU 12 VPD 3 PPD 3
    numaHost: VCPU 13 VPD 3 PPD 3
    numaHost: VCPU 14 VPD 3 PPD 3
    numaHost: VCPU 15 VPD 3 PPD 3

    получается вот так

  4. Андрей Вахитов говорит:

    numa: coresPerSocket= 8 maxVcpusPerVPD= 4
    А это зачем?

  5. Сергей говорит:

    Это автоматом так выставило
    а как нужно ?

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *