“Большие системы” для конечного пользователя означают значительные инвестиции в вычислительные ресурсы, и сразу же возникает вопрос эффективного управления этими мощностями. На этот раз оставим виртуализацию в стороне и рассмотрим динамическое управление ресурсами в пределах одной отдельно взятой операционной системы. Где это необходимо? Примеры:

  • Веб-сервер, поддерживающий несколько экземпляров одного и того же приложения;
  • Сервер, поддерживающий разные приложения (например СУБД и Apache) или HPC-приложения, каждое из которых должно работать с заданными параметрами быстродействия;
  • Сервер, поддерживающий приложения, нагружающие разные ресурсы (подсистемы) этого сервера, но требующие заданный уровень сервиса.

В замечаниях к выпуску Enterprise Linux 5 можно встретить такую фразу:

“…Cpuset обеспечивает механизм назначения узлов процессоров и памяти наборам задач, тем самым ограничивая распределение памяти и процессоров в пределах заданного cpuset. Механизм Cpuset является основным стандартом управления динамическим распределением задач в больших системах…”

Про Cpuset “в двух словах” я и хочу рассказать в этом посте. Данный механизм позволяет “на лету” распределять вычислительные ресурсы между различными задачами, ограничивая использование ОЗУ и ЦП “вычислительным доменом”, которому присвоена задача. Впервые поддержка Cpuset появилась в ядре 2.6.12. Патч, включавший данный функционал, был предложен в 2005 году, привносил достаточно небольшой объем кода, дополнительно не нагружая планировщик процессов. Cpuset расширяет возможности уже существовавших в ядре Linux механизмов, позволявших задать с использованием какого ЦП (sched_setaffinity) и ОЗУ (mbind, set_mempolicy) может выполняться задача.

Поскольку управление Cpuset осуществляется при помощи виртуальной файловой системы, самый простой способ проверить, скомпилировано ли ядро вашей системы с поддержкой cpusets - это команда:

[root@server1 ~]# cat /proc/filesystems | grep cpuset
nodev   cpuset

Начать работать с cpuset максимально просто:

1) Создадим и смонтируем специальную файловую систему cpuset

[root@server1 ~]# echo "cpuset /cs cpuset defaults 0 0" >> /etc/fstab
[root@server1 ~]# mkdir /cs
[root@server1 ~]# mount -a

В итоге все процессы “привязаны” к корневому и единственному существующему на данный момент “вычислительным домену”. У каждого процесса есть файл /proc/PID/cpuset, просмотрев который можно увидеть, к какому cpuset он привязан. В настоящий момент для любого процесса мы увидим картину:

[root@server1 ~]# cat /proc/1/cpuset
/

Кроме того, если посмотреть на специальную файловую систему cpuset, то внутри нашей директории /cs мы обнаружим ряд файлов, среди которых:

- cpus: список ЦП в этом cpuset

[root@server1 ~]# cat /cs/cpus
0-7

- mems: список узлов ОЗУ в этом cpuset

[root@server1 ~]# cat /cs/mems
0

- tasks: список процессов, привязанных к этому cpuset

[root@server1 ~]# cat /cs/tasks | wc -l
151

2) Теперь создадим “дочерний” cpuset. Это делается при помощи создания поддиректории внутри файловой системы cpuset:

[root@server1 ~]# mkdir /cs/cs1

Внутри /cs/cs1 мы увидим те же файлы, что и внутри корня файловой системы cpuset. Далее необходимо привязать ресурсы нашему новому вычислительному домену:

[root@server1 ~]# echo 0,3,7 > /cs/cs1/cpus
[root@server1 ~]# echo 0 > /cs/cs1/mems

3) Присваиваем какую-либо задачу домену cs1:

[root@server1 ~]# echo $(pidof syslogd) > /cs/cs1/tasks

В итоге мы видим:

[root@server1 ~]# cat /proc/$(pidof syslogd)/cpuset
/cs1

и изменившуюся маску ЦП для процесса syslogd:

[root@server1 ~]# cat /proc/$(pidof syslogd)/status | grep Cpus
Cpus_allowed:   00000089

Должен заметить, что наиболее полный из доступных источников по теме - это описание /usr/share/doc/kernel-doc-*/Documentation/cpusets.txt, к которому я и отсылаю вас за дополнительной информацией.