Ядра 1 и 2 сорта под Linux

Процессоры с P и E ядрами появились сравнительно недавно и как с ними уживаться все еще ломают голову разработчики.

Однако на самом деле эта дискриминация на первоклассные и второсортные ядра процессора появилась еще раньше. И пришлось изобретать свои костыли, чтобы важное запускалось на быстрых, а неважное на медленных ядрах.

Речь идет о турбо частоте. Суть в том, что практически у любого процессора базовая частота не имеет никакого значения. В режиме энергосбережения частота может быть сильно ниже базовой, а под полной загрузкой всех ядер частота также немного выше базовой (all core turbo). И конечно же, при условии отсутствия нагрузки на других, одно или несколько ядер могут повышать частоту еще выше до значения turbo.

Однако есть линейки процессоров (в частности это Xeon E5 v4), у которых определенные ядра ни при каких условиях не могут поднять частоту выше all core turbo. Будем называть их «медленными».

Все испытания провожу на домашнем роутере под ОС Debian и Xeon E5–1630v4 (4 ядра, 8 потоков, 3.7 Ггц базовая, 4.0 Ггц турбо)

apt install linux-cpupower

По-умолчанию скорей всего (если специально не менять ничего в BIOS) будут включены все C-states процессора:

watch -n0.5 «cpupower monitor -c»

d3d4c6c7eb226df5ca22dbbcd3d3de36.png

В кратце: это уровни энергосбережения. Чем выше уровень, тем в более глубоком сне находится ядро и тем дольше оно из него выходит. Поэтому там где нужна больше скорость работы, а не энергосбережение, то рекомендуется держать ядра не глубже C3. А где нужна самая максимальная отзывчивость — C1, однако в этом режиме уже не будет никаких turbo частот. Поэтому ограничить на сервере до C3 — оптимальное решение, когда и хорошая отзывчивость и ядра могут повышать частоту до turbo. Помимо C-states есть также другие параметры, которыми можно смещать работу процессора либо в сторону скорости, либо в сторону экономии энергии (governor, performance bias… и все эти изменения делаются/не_делаются как в ОС, так и в BIOS — нужно рассматривать конкретный процессор и конкретную мат. плату), но здесь не об этом.

Подчеркну лишь, что в большинстве случаев по-умолчанию баланс смещен именно в сторону экономии энергии. И без ручного вмешательства процессор может не быть таким быстрым как мог бы, хотелось бы…

Проверяем теорию о медленных ядрах. Отключаем у всех ядер C1E и C3:

cpupower -c all idle-set -d2
cpupower -c all idle-set -d3

И дальше поочередно отключаем C6 у каждого из ядер, загоняя принудительно только это ядро в C1

cpupower -c 0 idle-set -d4

bc87df68991bf19505a4605153bc1337.png

Видим, что ядро 0 теперь 99% времени простаивает в C1, т.е. полностью готово к работе. Хотя и работы на нем никакой не выполняется. Но главное, видим что частота его не выше 3.8 Ггц

Включаем обратно cpupower -c 0 idle-set -e4

И отключаем C6 у следующего:

cpupower -c 4 idle-set -d4

69539f8125e1c2b55b809a38d067858f.png

Виртуальное ядро 4 также у нас не подымается выше 3.8 Ггц

cpupower -c 1 idle-set -d4

ef862f7080feac2287b85081d5053995.png

А вот и первое ядро здорового человека, которое может подняться под 4 Ггц. Не совсем т.к. помимо этой программной настройки есть еще аппаратное управление в самом процессоре, на которое никак не повлиять. До самого максимума ядро сможет разогнаться только если на нем еще и нагрузка хоть какая-то будет.

Также мы видим, что следующее ядро 5 тоже подскочило в частоте. Т.е. виртуальные ядра 1 и 5 — это одно физическое ядро и частоты у них связаны.

cpupower -c 5 idle-set -d4

4f584995c623706c56f0d923f794050d.png

Соответственно разгоняя ядро 5, поднимается частота и у ядра 1

cpupower -c 2 idle-set -d4

e17a9ada99653668c48d23043a5b67a0.png

cpupower -c 6 idle-set -d4

ce33961431d0e58cfe29e71141be688f.png

Выяснили, что ядра 2 и 6 также могут, если захотят.

cpupower -c 3 idle-set -d4

46880254921d3cef60b8a026cb19f0f6.png

cpupower -c 7 idle-set -d4

81c96a59c7bbbfbe48be3e573585a2d9.png

А ядра 3/7 как и 0/4 тоже не выше 3.8 Ггц.

Итого расклад по максимальным частотам у нас получился такой:

0 — 3.8

4 — 3.8

1 — 4.0

5 — 4.0

2 — 4.0

6 — 4.0

3 — 3.8

7 — 3.8

Так в чем же проблема?

Обычно процессы запускаются на первом попавшем случайном ядре. Конечно это не доставляет неудобств в большинстве случаев и никто вообще не заморачивается такими мелочами. Особенно если задачи многопоточные и малотребовательные к CPU — типа Nginx например. Однако есть случаи, когда запускаемый процесс точно лишь однопоточный и внутренняя жаба начинает душить от осознания того что этот процесс в 50% случаев (на данном процессоре) запускается на медленных ядрах и выполняется хоть немного, но медленней чем мог бы…

На помощь приходит комманда taskset

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

Для примера запакуем в 1 поток полугигабайтный каталог /usr/share на ядре 0:

ef64688f1d0965a4053d24e3e40a29ff.png

и потом на ядре 1:

bae62516461db7959330b3e2e39603a4.png

Отличие в 5 сек. Да, разница не такая большая как была бы с современными P и E ядрами, но она есть.

Еще примечательно, что даже подымая частоту лишь на 1 из ядер, все остальные также подтягиваются к 3.8, хоть они и находятся в C6 режиме энергосбережения. И если просто поднять частоту на всех быстрых ядрах, то итоговая максимальная частота каждого будет заметно не дотягивать до 4.0 Ггц.

0480d907d942570fd0b02b6b94cb5883.png

Запустим архивирование в 1 поток на одном из быстрых ядер:

75daa8075d8e590de9c2cfcb035721b3.png

Видим, что при условии когда все остальные ядра находятся в покое, частота этого загруженного ядра увеличивается практически до самого верхнего потолка в 4.0 Ггц.

Загрузим все 4 быстрых ядра 4-х поточным архивированием:

58f5faf357af36b5b4d4a2aed8459753.png

Все еще хорошо конечно, однако заметно как максимальная частота каждого отдалилась от отметки 4.0 Ггц.

Ну и загрузим по максимуму все 8 ядер:

622dddcf05f983ce65c62ce8d35da29c.png

Получили all core turbo в 3.8 Ггц.

Раскрасив на графике мониторинга (collectd + rrdtool) ядра 1,5,2,6 красным, а остальные зеленым (не смотрим на подпись под графиком), наглядно видим как зеленые никогда не выходят выше, куда могут красные:

59f6ed17e5b1b173da345721a5a92a9c.png

Как это использовать на практике? Каждый решит для себя. На своем хостинге к примеру, я ограничил малозначимые процессы только медленными ядрами. Ни к чему чтобы FTP, DNS и подобные задачи вообще присутствовали на быстрых ядрах. Чтобы на этих быстрых исполнялось лишь то, что действительно важно — MySQL и PHP. В файле службы добавляем все тот же taskset и список медленных ядер (в данном случае процессор E5–1650v4):

ab11cf32e57cddc7dc3480564b2efbbc.png

Можно конечно сделать обратное ограничение, повесить определенные задачи только на быстрые ядра:

bb5f34d5a70f6ee6dfe0259ba9a0cefd.png

MySQL будет работать замечательно и максимально возможно быстро…, но лишь до поры пока нагрузка не большая и в основном однопоточная. Нужно быть осторожным т.к. если к базам будут приходить больше 4 параллельных запросов, то суммарная производительность конечно же наоборот уменьшится, ведь мы по-сути ограничили этот процесс лишь 4 мя ядрами.

В целом конечно же подобные процессоры очень неудобны и гораздо лучше когда все ядра равны.

704d74fdbc18d1d448cfb7cb85cb5a4a.png

Особенно печально если ваш VPS хостер использует подобные процессоры и вас поселят именно на подобные медленные ядра, которые никогда, ни при каких условиях не смогут приблизиться к турбо-частоте (За которую вы наверняка заплатили, поверив рекламе). И вы врядли сможете подобрать слова, чтоб объяснить/доказать проблему поддержке.

© Habrahabr.ru