Linux привязать процесс ядру

Taskset — привязка процесса к ядрам CPU в Linux

По умолчанию процессы в Linux используют все ядра процессора, но иногда необходимо освободить 0 ядро, которое обычно больше всего загружено или назначить некоторые процессы только на второй CPU и т.д., в этом случае поможет taskset.

Переключимся на root пользователя:

Узнаем ID процесса mc или любого другого нужного процесса:

Результат у меня был 249 , посмотрим каким ядрам назначен этот процесс:

Мой вывод содержал все ядра:

pid 249’s current affinity list: 0-11

Укажем ядра или процессоры которые хотим задействовать под данный процесс:

root@U0LC3:~# taskset -pc 10-11 249
pid 249’s current affinity list: 0-11
pid 249’s new affinity list: 10,11

Если с указанным именем запущено несколько процессов, то можно использовать скрипт (на примере процесс mc):

(for thread in $(ps -T -C mc | awk » | grep -E ‘3’); do /usr/bin/taskset -pc $thread; done)

Bывод в моём случае был следующий:

pid 249’s current affinity list: 10,11
pid 307’s current affinity list: 0-11
pid 323’s current affinity list: 0-11

Теперь привяжем все эти процессы к нужным ядрам:

(for thread in $(ps -T -C mc | awk » | grep -E ‘6’); do /usr/bin/taskset -pc 10-11 $thread; done)

pid 249’s current affinity list: 10,11
pid 249’s new affinity list: 10,11
pid 307’s current affinity list: 0-11
pid 307’s new affinity list: 10,11
pid 323’s current affinity list: 0-11
pid 323’s new affinity list: 10,11

Чтобы изменения не сбросились после перезапуска операционной системы, укажем команду например в файле /etc/rc.local.

Источник

Отключить/включить ядра CPU в Linux

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

Выведите информацию о доступных ядрах:

lscpu - информация о процессорах и ядрах в консоли linux

CPU(s): 3 On-line CPU(s) list: 0-2

В этом примере для гостевой ОС на виртуальной машине Linux доступны три ядра 0, 1 и 2.

В Linux вы можете отключить любые ядра процессора, кроме нулевого (CPU0).

Чтобы отключить ядра 1 и 2, выполните команду:

chcpu - отключить ядро в linux

CPU 1 disabled CPU 2 disabled

Проверьте теперь какие ядра доступны:

On-line CPU(s) list: 0 Off-line CPU(s) list: 1,2

Также можно вывести информацию о доступных процессорах так:

$ grep «processor» /proc/cpuinfo

Чтобы включить ядра процессора, выполните:

CPU 1 enabled CPU 2 enabled

Также вы можете отключить определенное ядро командой. В этом примере мы отключаем CPU1:

$ sudo echo 0 | sudo tee /sys/devices/system/cpu/cpu1/online

Проверьте сообщения в dmseg:

[ 2257.253801] smpboot: CPU 1 is now offline

Чтобы включить его, выполните:

$ sudo echo 1 | sudo tee /sys/devices/system/cpu/cpu1/online

Если вы хотите, чтобы Linux всегда загружалась с меньшим количество доступных ядер, нужно настроить параметр ядра maxcpus=N.

N в этом случае – это количество доступных ядер процессора, доступных в Linux.

$ sudo mcedit /etc/default/grub

Измените строку следующим образом:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash maxcpu=2"

grub - ограничить количество доступных проессоров в linux

Вы можете использовать отключение ядер CPU в Linux, когда нужно уменьшить количество vCPU для виртуальной машины Linux и вы хотите протестировать, как работает операционная система и приложения с меньшим количеством доступных vCPU.

Читайте также:  Shared file system on linux

Также в Linux вы можете запускать приложения на определённых ядрах с помощью CPU affinity. Чтобы получить информацию о привязки определенного процесса к ядрам, выполните:

pid 894's current affinity mask: 3
pid 894's current affinity list: 0,1

taskset привязка процесса к ядрам cpu в linux

Этому процессу разрешено выполняться на ядрах 0 и 1.

Чтобы разрешить запушенному процессу выполняться только на CPU0, выполните:

pid 894's current affinity list: 0,1 pid 894's new affinity list: 0

Или, чтобы разрешить процессу firefox использовать ядра с 0 по 3:

$ sudo taskset -c 0-3 firefox

Источник

Борьба за ресурсы, часть 6: cpuset или Делиться не всегда правильно

Во время разговоров о cgroups пользователи Red Hat довольно часто задают один и тот же вопрос: «У меня есть одно приложение, очень чувствительное в смысле задержек. Можно ли с помощью cgroups изолировать это приложение от остальных, привязав его к определенным процессорным ядрам?»

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

В детстве нам часто говорили, что делиться – это хорошо и правильно. По большому счету, так оно и есть. Но бывают исключения.

Как мы писали в первом посте этой серии, по умолчанию Red Hat Enterprise Linux 7 ведет себя как сферическая добрая бабушка. В том смысле, что она старается справедливо распределять системные ресурсы между всеми, кто их просит. Однако в реальной жизни у бабушек бывают любимчики, которым достается больше. В переводе на сисадминский это означает, что бывают ситуации, когда одни приложения или сервисы важнее других, поэтому им надо уделять всё возможное внимание, чтобы они были максимально отзывчивы.

В Red Hat Enterprise Linux 7 это делается в два этапа:

  1. Изолируем часть процессорных ядер, чтобы передать их в эксклюзивное пользование такому приложению.
  2. Создаем группы cgroups и юнит-файлы, привязывающие это приложение к изолированными ядрам.

Небольшое отступление касательно примеров из этих постов

В Hat Enterprise Linux 7.4 изменился механизм работы с недолговечными слайсами, типа пользовательских сеансов. В результате для них больше нельзя менять настройки cgroup на лету, вносить постоянные изменения в конфигурацию, а также создавать файлы drop-in с помощью команды systemctl set-property. Да, это обидно, но так уж решило сообщество разработки Linux. Хорошая новость в том, что эти изменения не затронули службы. То есть, если приложения запускаются и останавливаются через юнит-файлы (работают в качестве демонов), то все наши примеры работают. Кроме того, остается возможность создавать собственные cgroups с помощью таких древних инструментов, как cgcreate и cgset, и затем помещать в эти группы пользовательские сеансы и процессы, чтобы задействовать CPU-шары и прочие регуляторы. В жизни все меняется, поэтому нам остается только приспосабливаться и изобретать новые техники. А теперь переходим к сегодняшней теме.

Устраиваем сепаратизм с помощью isolcpus

Одна из самых важных составляющих в ядре Linux – это планировщик (диспетчер) процессов. Если чуть глубже, то процесс – это исполняемый код, являющийся часть приложения или сервиса. По сути, процесс состоит из серии инструкций, которые компьютер выполняет, делая ту или иную работу, будь просмотр котиков или что-то посерьезнее.

Читайте также:  Kali linux откат системы

Выполнением этих инструкций занимается центральный процессор, он же CPU. На современных компьютерах CPU, как правило, состоит из нескольких процессоров, которые называются ядрами.

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

Поэтому нам надо как-то сказать планировщику, чтобы он не трогал часть процессорных ядер, то есть не отдавал им какие ни попадя процессы. А затем мы сами (или с помощью какого-то другого процесса) будем принудительно сажать на эти изолированные от планировщика ядра те процессы, которые посчитаем нужными. Это можно сделать с помощью параметра isolcpus в строке загрузки ядра в конфигурационном файле grub. В примере ниже у нас машина с четырьмя ядрам, на которой есть два файла grub: один лежит в /etc/default и называется grub.noiso (это резервная копия конфигурации по умолчанию), а второй лежит там же и называется просто grub, чтобы его подхватывал grub2-mkconfig. Этот второй файл подредактирован так, чтобы изолировать ядра 1-3 от планировщика процессов.

ВНИМАНИЕ: в Red Hat Enterprise Linux 7 никогда не надо вручную модифицировать файл grub.conf в папке /boot. Вместо этого внесите необходимые изменения в /etc/default/grub и затем пересоберите grub.conf file с помощью соответствующей утилиты, например, так:

При использовании параметра isolcpus надо через запятую перечислить высвобождаемые процессорные ядра, нумерация начинается с 0. После перезагрузки системы планировщик процессов не будет использовать эти ядра ни для чего, за исключением определенных процессов системного уровня, которые ДОЛЖНЫ БЫТЬ на каждом ядре. Чтобы проверить, сработал ли наш метод, запустим несколько нагрузочных процессов и затем посмотрим загрузку каждого ядра с помощью команды top.

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

Привязываем процессы к ядрам с помощью cpuset

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

К чему эти предостережения? К тому, что мы будем делать, в общем-то, простые вещи с помощью инструментария libcgroup, о котором писали в прошлом посте. Если помните, это просто набор команд для создания, модифицирования и уничтожения групп cgroups. Вообще-то они являются частью Red Hat Enterprise Linux 6, но их можно установить и на Red Hat Enterprise Linux 7, хотя не исключено, что в будущем эта возможность исчезнет. Вкратце напомним основные рекомендации по использованию libcgroup:

  1. Используйте systemd для управления теми контроллерами-регуляторами cgroup, которые находятся под управлением самого systemd (это CPU, память и блочный ввод-вывод).
  2. Используйте инструменты libcgroup для управления всеми остальными контроллерами-регуляторами cgroup.
  3. Будьте очень осторожны в плане незапланированных последствий ваших действий.
Читайте также:  Linux intel vga drivers

Давайте проверим каталог /sys/fs/cgroup filesystem на системе из нашего примера. Как видим, каталог cpuset уже существует, поскольку этот контроллер – это часть ядра (хотя он и не находится под управлением systemd). Однако в нем пока нет cgroups, поэтому мы видим в этом каталоге только настройки по умолчанию.

Проверим, что на нашей машине установлен инструментарий libcgroup:

Если не установлен, то это легко исправить командой yum install libcgroup, даже перезагрузка не понадобится.

Теперь создадим cpuset. Для этого мы будем использовать следующие команды, чтобы создать новую cgroup для cpuset и прописать ее свойства:

Команда Cgcreate создает cgroup с именем testset и размещает ее внутри контроллера cpuset. Затем мы назначаем третье ядро нашей ВМ этому новому cpuset’у и выделяем ему же NUMA-зону 0. Даже если ваша система не использует NUMA (а наша как раз не использует), зону все равно надо прописывать, иначе не получится назначать задачи группе cgroup. Теперь проверим, что в файловой системе создался каталог testset, и посмотрим, что у него внутри.

Как видим, наши изменения на месте, но на этом cpuset’е пока что не выполняется ни один процесс. Как посадить сюда какой-нибудь процесс?

Это можно сделать несколькими способами:

  • Можно вбить PID существующего процесса в файл tasks. Это работает, но не очень красиво.
  • Можно воспользоваться cgexec и указать группу при запуске процесса. Это работает, если приложение не является демоном; к тому же, все это можно красиво прописать в скрипт запуска приложения.
  • Для приложения, которое запускаются в качестве демона под управлением systemd, можно создать service-файл.

Мы запустили foo.exe, он в свою очередь запустил дочерний процесс, который только и делает, что активно грузит процессор. Опция —sticky в команде cgexec говорит, что «любой дочерний процесс должен оставаться в той же cgroup, что и родительский процесс». Так что это важная опция, и ее надо запомнить. Теперь мы видим, что в нашей cgroup крутятся два процесса, и мы знаем их PID’ы. Глянем top:

Как видим, CPU 3 теперь загружен под завязку, а остальные прохлаждаются.

А вот как выглядит юнит-файл для запуска того же приложения в качестве сервиса systemd:

В юнит-файле есть три команды ExecStartPre, которые выполняют настройки, которые мы уже успели сделать руками. Затем идет команда ExecStart, которая запускает приложение. А при остановке приложения, команда ExecStopPost подчищает за собой, удаляя cgroup.

Как видите, в последнем примере мы создали новую cgroup по имени set1. Мы сделали это, чтобы показать, что можно иметь несколько активных cgroups, которые делят одни и те же CPU. Кому это может показаться полезным, а кого-то наоборот запутать.

Ну что, все работает? Похоже, да!

А теперь завершим работу нашего сервиса и проверим, что cgroup уничтожилась:

ВНИМАНИЕ: Группы cgroup, создаваемые с помощью cgcreate, не сохраняются после перезагрузки. Поэтому создание таких групп надо прописывать в сценариях запуска и юнит-файлах.

Так что теперь в вашем арсенале есть еще парочка инструментов для работы с cgroups. Надеемся, они пригодятся!

Другие посты по cgroups из нашей серии «Борьба за ресурсы» доступны по ссылкам:

Источник

Оцените статью
Adblock
detector