Linux: работа с процессором и процессами (lscpu, interrupts, smp irq affinity, isolcpus, taskset, cpuset/cset shield)

Core (logical/physical) numbers

Количество процессинг-юнитов (физических CPU). Может не совпадать с top (добавляются логические CPU,  как в примерах ниже).

$ nproc
4
 nproc - print the number of processing units available.

Понятнее всего количество физических и логических ядер посмотреть в выводе lscpu

    • логические (общее количество на систему) в виде CPU(s). Отображаются все CPU, включая созданные hyperthreading –  в данном выводе 2 процессора E5-2620 v3 с 6 физическими ядрами на борту и 12 потокама (12 * 2 = 24).
    • физические (количество на сокет) в виде Core(s) per socket
# E5-2620 v3
lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 24
On-line CPU(s) list: 0-23
Thread(s) per core: 2
Core(s) per socket: 6
Socket(s): 2
NUMA node(s): 2
Vendor ID: GenuineIntel
CPU family: 6
Model: 63
Model name: Intel(R) Xeon(R) CPU E5-2620 v3 @ 2.40GHz

top
%Cpu0 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 2.1 us, 2.1 sy, 0.0 ni, 95.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu2 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu4 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu5 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu6 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu7 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu8 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu9 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu10 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu11 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu12 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu13 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu14 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu15 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu16 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu17 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu18 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu19 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu20 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu21 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu22 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu23 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
# i3-4360
lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Thread(s) per core: 2
Core(s) per socket: 2
Socket(s): 1
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 60
Model name: Intel(R) Core(TM) i3-4360 CPU @ 3.70GHz

top
%Cpu0 : 0.4 us, 0.0 sy, 0.0 ni, 99.6 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 0.4 us, 0.4 sy, 0.0 ni, 99.1 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu2 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

 

isolcpus
  • Isolcpus deprecated функционал. У isolcpus есть два существенных недостатка, которых нет у ниже описанного cpuset shield (cset shield):
    • для ядер CPU, которые находятся в изоляции не работает scheduler операционной системы и нагрузка одного приложения не будет распределяться по нескольким CPU, даже если так настроен taskset
    • isolcpus можно настроить только с перезагрузкой (изменение grub)
Since isolated CPUs are excluded from SMP balancing and the scheduler algorithm, it's not desirable to use them in situations where you want a process balanced across multiple CPUs. In such cases, shielding is more desirable (see the man page for cset-shield):
- Normally, when I have isolcpus, starting a process with taskset -c 2-32 means all threads end up on core 2 as isolcpus "removes cores from scheduler" as I was told so there is no load balancing.
-  Similar to taskset, it's possible to define more than one CPU in a cpuset, however, due to the nature of isolated CPUs, only the first defined CPU will be effective.
- Cgroup cpuset is not balancing tasks on CPUs isolated via isolcpus kernel parameter Automated load balancing of a process/task across multiple isolated CPUs is not possible.

Изоляция CPU позволяет “вынести” CPU из общих ресурсов и в последующем прибиндить его к конкретной app, которая потенциально будет работать более стабильно/производительно в такой конфигурации за счет отсутствия переключения контекста и кеша. По факту, пишут, что преимущества изоляции сейчас минимальны и многие приложения прекрасно масштабируются/балансируются на CPU без присвоения им конкретных ядер обработки (запуск нескольких instance приложения без присвоения каждому конкретных ядер).

Since isolated CPUs are excluded from SMP balancing and the scheduler algorithm, it's not desirable to use them in situations where you want a process balanced across multiple CPUs. In such cases, shielding is more desirable (see the man page for cset-shield). 

The isolcpus option can be used to isolate cores from the Linux scheduler. The isolated cores can then be used to dedicatedly run HPC applications or threads. This helps in better application performance due to zero context switching and minimal cache thrashing. It has been verified that core isolation has minimal advantage due to mature Linux scheduler in some circumstances.

Пример настройки – 1) выводим из системы 7 ядер из 8 или 2) с 1 по 19. Нулевое ядро в обоих случаях оставляем системе в GRUB cmdline.

vim.tiny /etc/default/grub
   GRUB_CMDLINE_LINUX="isolcpus=1,2,3,4,5,6,7"
   GRUB_CMDLINE_LINUX="isolcpus=1-19"
sudo update-grub
Проверка isolcpus. Основной работающий способ – по первому процессу (в моем случае c 3.2.0-4-amd64 только этот способ работал).
You can also use taskset pointed to PID 1. As PID 1 is the standard PID for the first task launched by the kernel, we can take as a pretty good indication that it will reflect whether we have isolcpus working. As in:

$taskset -cp 1
pid 1's current affinity list: 0,1

$lscpu | grep CPU.s
CPU(s): 4
On-line CPU(s) list: 0-3
NUMA node0 CPU(s): 0-3

As it can be seen, lscpu is showing 4 CPU/cores, while taskset is only showing 0,1, so this shows isolcpus is working here.

Так же можно посмотреть с каким CMDLINE была загружена система.

# cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-3.2.0-4-amd64 root=UUID=fcd249ff-8e89-408d-bc51-e8868dc14748 ro isolcpus=1 quiet

 

cpuset shield (cset shield)
  • (CPUSET/CSET SHIELD, ISOLCPUS, AFFINITY, IxChariot) Конфигурация системы (нагрузчик IxChariot Endpoint) которую я настраивал для создания высокой нагрузки (более 10 gbps TCP трафиком), всего 4 ядра CPU в системе:
    • использовал cpuset с shield (cset shield) для ядер CPU 2-3, на которых запускается endpoint процесс с балансировкой нагрузки между ядрами
    • использовал isolated CPU для ядра 1 (isolcpus), прерывания очередей нагрузочных интерфейсов (сетевой карты 10G) переведены на отдельное изолированное ядро 1 (smp_affinity) – периодически были всплески на CPU1 до 80%, но редко (для отлова чаще всего нужно использовать top с настройками обновления чаще 1 раз в 3с) в отличии от конфигураций shield 1-3 или default конфигурации
    • системные процессы работали на оставшемся ядре 0 – конфиги ниже однозначно проявили себя хуже
      • если все держать в общем пуле (linux + endpoint + прерывания) – система (SSH) не тормозит, но производительность упирается в прерывания на нулевом ядре
      • если на CPU 0 обрабатывать как прерывания (только на нем), так и системные задачи (linux + прерывания) – система явно упирается в прерывания на нулевом ядре и даже SSH начинает тормозить, результаты ухудшаются
      • если выделять два ядра CPU0 + CPU1 под общие задачи прерывания и системные задачи (linux + прерывания), а приложение держать на отдельных двух – все ок и с системой и с результатами тестирования производительности приложения, но потенциально вариант с разделением прерываний на отдельный CPU более стабилен и я остановился на нем

Включает в себя достоинства isolcpus и при этом в этом функционале отсутствуют недостатки isolcpus – одно приложение в группе cset shield балансируется между выделенными в shield ядрами, настройка cset shield возможна без перезагрузок системы.

# INSTALL CPUSET/CSET
apt-get install cpuset

# CHECK THAT SHIELD OFF
taskset -cp 1
  pid 1's current affinity list: 0-3

# CREATE SHIELD
cset shield --cpu 2-3 --kthread on

# RUN APP IN SHIELD
cset shield --exec /usr/local/some_application
# ALTERNATE
set shield --shield --pid 3237

# DELETE APP FROM SHIELD
cset shield --unshield --pid 3237

# CHECK
taskset -cp 1  # check system pid
  pid 1's current affinity list: 0-1
taskset -cp 19  # check app pid
  pid 19's current affinity list: 2-3
cset shield -s  # show shield load
  cset: "user" cpuset of CPUSPEC(2-3) with 13 tasks running
  cset: done

Если нужно, чтобы cset настраивался сразу при запуске системы – это легко сделать добавив те же команды настройки cset в автостарт системы (напр. /etc/rc.local или systemctl). Единственная особенность – запуск приложения в shield и cset нужно разносить каким-то ожиданием или sleep (на практике достаточно 5 секунд) или проверкой создания, иначе приложение не запустится т.к. cset shield еще не будет создан.

maxcpus

Изменять количество активных CPU в сторону понижения надежнее всего через maxcpus.

I have got some interesting experience with 
> switching on/off the CPU cores. First, I did the on/off switching of 
> the i-th CPU core by writing 1/0 values into the 
> /sys/devices/system/cpu/cpu$i/onlinefile of the working Linux kernel 
> [2]. Whereas it seemed to work well, when the query rates were 
> moderate (a few times ten thousand queries per second), it caused 
> problems in the second case, when I used up to 3 million queries per 
> second query rates, and thus I rather set the number of active CPU 
> cores at the DUT by using the maxcpus=nkernel parameter.
interrupts, SMP IRQ affinitY

Linux kernels have the ability to balance hardware interrupt requests across multiple CPUs or CPU cores. The feature is referred to as SMP IRQ Affinity and results in better system performance as well as better CPU utilization.

CPU ID Binary Hexadecimal
CPU 0 0001 1
CPU 1 0010 2
CPU 2 0100 4
CPU 3 1000 8
    • прерывания – это триггер, сгенерированный девайсом (сетевой картой, дисковым контроллером), получив этот триггер CPU должен его обработать (в том числе остановив текущую задачу)
When a hardware component (such as a disk controller or an Ethernet NIC) needs to interrupt the work of the CPU, it triggers an interrupt. The interrupt notifies the CPU that an event occurred and the CPU should suspend its current work to deal with the event.
    • во многих случаях несмотря на низкую совокупную утилизацию CPU производительность низка из-за высокой загрузки ядра (или ядер) CPU, обрабатывающего прерывания – к примеру без SMP IRQ affinity все прерывания всех сетевых карт распределены на нулевое ядро CPU0, что, очевидно, может быть bottleneck
In many cases, when overall CPU usage is low but performance is poor, it is usually the CPU core specified to handle interrupts is fully occupied. Let's take NIC interrupts as an example. Without the SMP IRQ affinity, all NIC interrupts are associated with CPU 0. As a result, CPU 0 is overloaded and cannot efficiently process network packets, causing a bottleneck in performance.
    • распределение прерываний на специальные CPU/группы CPU (лучше группы) в виде SMP IRQ affinity появилось еще в Linux ядре 2.4, к примеру можно переводить полностью NIC на определенные ядра или более стандартно – переводить определенные очереди каждой NIC на отдельные ядра (используя RSS или Soft RSS RPS/RFS). Нежелательно использовать CPU0 для прерываний RPS.
Balancing network interrupts among multiple CPUs increases the performance of network-based operations.

In kernel 2.4 and later, Linux improves the capability of assigning specific interrupts to the specified processors (or processor groups). This is called the SMP IRQ affinity, which controls how the system responds to various hardware events. You can limit or redistribute the server workload so that the server can work more efficiently. After you configure the SMP IRQ affinity, multiple NIC interrupts are allocated to multiple CPUs to distribute the CPU workload and speed up data processing. The SMP IRQ affinity requires NICs to support multiple queues. A NIC supporting multiple queues has multiple interrupt numbers, which can be evenly allocated to different CPUs. In the following example, interrupt 27 is allocated to CPU 0 for processing. Generally, you are recommended to leave CPU 0 unused.
    • ((с другой стороны в Linux по умолчанию работает NAPI)) по идее задачу динамически должен и решает IRQbalance, но по факту
      • он часто выключен по умолчанию
      • зачастую даже при включении все равно более правильным решением является настройкам вручную прерываний и отключение IRQbalance (лаг на адаптацию при спайках нагрузки, высокий уровень context switch, глюки)
Most Linux installations are not configured to balance network interrupts. The default network interrupt behavior uses a single processor (typically CPU0) to handle all network interrupts and can become a serious performance bottleneck with high volumes of network traffic. Balancing network interrupts among multiple CPUs increases the performance of network-based operations.

IRQbalance is applicable to most scenarios. However, in scenarios requiring high network performance, you are recommended to bind interrupts manually. IRQbalance can cause some issues during operation:
(a) The calculated value is sometimes inappropriate, failing to achieve load balancing among CPUs.
(b) When the system is idle and IRQs are in power-save mode, IRQbalance distributes all interrupts to the first CPU, to make other idle CPUs sleep and reduce energy consumption. When the load suddenly rises, performance may be degraded due to the lag in adjustment.
(c) The CPU specified to handle interrupts frequently changes, resulting in more context switches.
(d) IRQbalance is enabled but does not take effect, that is, does not specify a CPU for handling interrupts.
  • IRQbalance помогает в средних сценариях, но по факту:
    • Он иногда не работает (у меня так же было) и это приводит к деградации производительности/росту задержек и потерь
    • С высокой прозводительностью зачастую лучше настроить прерывания вручную – IRQbalance is applicable to most scenarios. However, in scenarios requiring high network performance, you are recommended to bind interrupts manually.

Настройка affinity позволяет:

    1. привязать процесс к конкретному ядру (конкретным) CPU
    2. привязать очередь прерываний к конкретному ядру,  например, очередь прерываний с сетевой карты биндится к конкретному ядру процессора (напр. так реализовано в TRex)

Часто используется в задачах генерации/обработки большой нагрузки. Привязка приводит к повышению стабильности производительности и росту данной производительности (пример описан в ESXi). Affinity работает зачастую в связке c распределением потоков на базе расчета hash для передаваемых потоков:

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

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

 

Пример моей настройки прерываний на отдельное ядро на практике (работало)

  • Распределение прерываний в smp_affinity появляется сразу после UP интерфейса, независимо от того, есть ли линк или нет. Если интерфейс не в UP – прерывания распределить не получится.
/proc/interrupts до настройки smp_affinity.
while true; do echo; echo; grep -w "CPU0\|Rescheduling\|eth8\|eth9" /proc/interrupts | sort -n; sleep 1; done
CPU0 CPU1 CPU2 CPU3
RES: 84049 43750986 110517787 110615940 Rescheduling interrupts
166: 82474083 0 0 0 IR-PCI-MSI-edge eth8-TxRx-0
167: 24042806 0 0 0 IR-PCI-MSI-edge eth8-TxRx-1
168: 59272802 0 0 0 IR-PCI-MSI-edge eth8-TxRx-2
169: 59361007 0 0 0 IR-PCI-MSI-edge eth8-TxRx-3
170: 4 0 0 0 IR-PCI-MSI-edge eth8
180: 82616626 0 0 0 IR-PCI-MSI-edge eth9-TxRx-0
181: 24207180 0 0 0 IR-PCI-MSI-edge eth9-TxRx-1
182: 59306623 0 0 0 IR-PCI-MSI-edge eth9-TxRx-2
183: 59334616 0 0 0 IR-PCI-MSI-edge eth9-TxRx-3
184: 2 0 0 0 IR-PCI-MSI-edge eth9
Настройка распределения прерываний на отдельное ядро (второе).
echo 000002 > /proc/irq/166/smp_affinity
echo 000002 > /proc/irq/167/smp_affinity
echo 000002 > /proc/irq/168/smp_affinity
echo 000002 > /proc/irq/169/smp_affinity
echo 000002 > /proc/irq/170/smp_affinity
echo 000002 > /proc/irq/180/smp_affinity
echo 000002 > /proc/irq/181/smp_affinity
echo 000002 > /proc/irq/182/smp_affinity
echo 000002 > /proc/irq/183/smp_affinity
echo 000002 > /proc/irq/184/smp_affinity
/proc/interrupts после настройки smp_affinity (CPU0 более не инкрементировался).
while true; do echo; echo; grep -w "CPU0\|Rescheduling\|eth8\|eth9" /proc/interrupts | sort -n; sleep 1; done
CPU0 CPU1 CPU2 CPU3
RES: 38502 44083017 180343133 172478449 Rescheduling interrupts
166: 83784996 680 0 0 IR-PCI-MSI-edge eth8-TxRx-0
167: 24543343 42381024 0 0 IR-PCI-MSI-edge eth8-TxRx-1
168: 60286755 35225747 0 0 IR-PCI-MSI-edge eth8-TxRx-2
169: 59985599 34032738 0 0 IR-PCI-MSI-edge eth8-TxRx-3
170: 2 0 0 0 IR-PCI-MSI-edge eth8
180: 83957687 682 0 0 IR-PCI-MSI-edge eth9-TxRx-0
181: 24894775 42820948 0 0 IR-PCI-MSI-edge eth9-TxRx-1
182: 60905927 35291571 0 0 IR-PCI-MSI-edge eth9-TxRx-2
183: 59187673 34322303 0 0 IR-PCI-MSI-edge eth9-TxRx-3
184: 4 0 0 0 IR-PCI-MSI-edge eth9

Настройка распределения прерываний на все ядра.

echo 00000f > /proc/irq/65/smp_affinity # eth0-tx-0
echo 00000f > /proc/irq/66/smp_affinity # eth0-tx-1
echo 00000f > /proc/irq/67/smp_affinity # eth0-tx-2
echo 00000f > /proc/irq/68/smp_affinity # eth0-tx-3
echo 00000f > /proc/irq/69/smp_affinity # eth0-rx-0
echo 00000f > /proc/irq/70/smp_affinity # eth0-rx-1
echo 00000f > /proc/irq/71/smp_affinity # eth0-rx-2
echo 00000f > /proc/irq/72/smp_affinity # eth0-rx-3

Посмотреть привязку процесса к CPU

Посмотреть привязку PID к CPUI можно множеством способов. Первый способ с taskset считаю самый простой и надежный, пользовался им при работе с isolcpus, cset shield (выше).

# С помощью самого taskset
~$ taskset -p 6099
pid 6099's current affinity mask: 3

# С помощью ps (столбец PSR)
sh-4.4# ps -eo pid,tid,class,rtprio,ni,pri,psr,pcpu,stat,wchan:14,comm | grep softirq
PID TID CLS RTPRIO NI PRI PSR %CPU STAT WCHAN COMMAND
9 9 TS - 0 19 0 5.7 S - ksoftirqd/0
16 16 TS - 0 19 1 0.0 S - ksoftirqd/1
21 21 TS - 0 19 2 0.0 S - ksoftirqd/2
26 26 TS - 0 19 3 0.0 S - ksoftirqd/3
31 31 TS - 0 19 4 0.0 S - ksoftirqd/4
36 36 TS - 0 19 5 0.0 S - ksoftirqd/5
41 41 TS - 0 19 6 0.0 S - ksoftirqd/6
46 46 TS - 0 19 7 0.0 S - ksoftirqd/7

# С помощью top (столбец P)
> Hit f to get into the Fields Management window
> Select P (Last Used Cpu) ((выбирается backspace))
> Esc
scroll coordinates: y = 1/195 (tasks), x = 1/13 (fields)
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND P
713 root 20 0 36760 27652 3656 S 0,0 0,3 165:04.34 collectl 1
335 root 20 0 60180 24396 7080 S 0,0 0,3 10:56.09 systemd-journal 0
1 root 20 0 107272 10412 7732 S 0,0 0,1 16:26.84 systemd 0
18601 www-data 20 0 1934252 10156 2472 S 0,0 0,1 0:00.00 apache2 1

# Можно даже сделать простой скрипт, который рассчитает количество процессов на ядро - в примере наиболее загруженны по количеству процессов ядра 0 и 1
root@us:~# ps -eo pid,tid,class,rtprio,ni,pri,psr,pcpu,stat,wchan:14,comm | awk '{print $7}' | sort | uniq -c | sort -n
1 PSR
7 10
7 11
7 3
7 4
7 5
7 7
7 8
7 9
8 2
9 6
55 1
73 0

 

 

Taskset

Привязать PID к CPU удобнее всего с помощью taskset. Так же можно использовать cset/cpuset без shield (с shield описано выше).

# Можно напрямую указать конкретный CPU (affinity), range или list (man taskset --cpu-list 0-2,6)
taskset --cpu-list 1 /root/redkin/tcpreplay-master/src/tcpreplay -i enp3s0f1 --topspeed --loop=1000000000000 --duration=600 --preload-pcap /root/redkin/test.pcap &
taskset --cpu-list 2 /root/redkin/tcpreplay-master/src/tcpreplay -i enp3s0f1 --topspeed --loop=1000000000000 --duration=600 --preload-pcap /root/redkin/test.pcap &

# Можно оперировать coremask, но это чаще всего менее удобно
taskset 0xFFFFFFFF /root/redkin/tcpreplay-master/src/tcpreplay -i enp3s0f1 --topspeed --loop=1000000000000 --duration=600 --preload-pcap /root/redkin/test.pcap &

# HEX
~$ taskset -p 0x00000001 6099
pid 6099's current affinity mask: 3
pid 6099's new affinity mask: 1
~$ taskset -p 0x00000002 6099
pid 6099's current affinity mask: 1
pid 6099's new affinity mask: 2

# DECIMAL
 >sudo taskset -pc 7 17551
pid 17551's current affinity list: 7
pid 17551's new affinity list: 7

Могут быть проблемы с привязкой для kernel threads, по идее они решаются только персборкой ядра с отключением флага PF_NO_SETAFFINITY для kernel процессов, но не факт (не изучил до конца этот вопрос – сомнения на основе статьи).

 >ps -p 828
PID TTY TIME CMD
828 ? 00:00:00 nfsiod
>sudo taskset -pc 7 828
pid 828's current affinity list: 0-11
taskset: failed to set pid 828's affinity: Invalid argument

Many kernel threads set the flag PF_NO_SETAFFINITY:
To change the affinity, you would have to change the kernel.
https://stackoverflow.com/questions/25359565/how-one-can-set-affinity-for-kernel-threads
https://stackoverflow.com/questions/60100719/check-value-of-pf-no-setaffinity

 

Пример привязки на сетевом оборудовании

Прерывание на сетевой карте привязываем к ядру CPU. Из /proc/interrupts можно извлечь распределение прерываний по очередям.

Помещает очередь прерываний первого интерфейса (по умолчанию 60, если в качестве интерфейса захвата eth1) на ЦПУ 0.
cat 1 > /proc/irq/60/smp_affinity 

Если задействован второй интерфейс необходимо определить его очередь прерываний. Для этого выполнить команду:
grep <наименование интерфейса> /proc/interrupts 
В полученном списке необходимо найти очередь для RX. Для установки свободного процессора необходимо использовать следующую формулу: 2 в степени номер свободного процессора в шеснадцатиричной форме. Например 8 свободный процессор (2^7) = 128. В шестнадцатиричной форме равно 80.
cat 80 > /proc/irq/69/smp_affinity
Number cores: 8
pgrep <proc> | xargs -I PID_PROC taskset -p PID_PROC
pid 23116's current affinity mask: 2
pid 23117's current affinity mask: 4
pid 23118's current affinity mask: 8
pid 23119's current affinity mask: 10
pid 23120's current affinity mask: 20
pid 23121's current affinity mask: 40
pid 23122's current affinity mask: 80
pid 23123's current affinity mask: 100

 /interfaces |tr ',' '
> '| xargs -I ETH grep ETH /proc/interrupts | cut -d: -f1 | xargs -I IRQ_NUMBER head -v /proc/irq/IRQ_NUMBER/smp_affinity
==> /proc/irq/133/smp_affinity <==
0002
==> /proc/irq/134/smp_affinity <==
0004
==> /proc/irq/135/smp_affinity <==
0008
==> /proc/irq/136/smp_affinity <==
0010
==> /proc/irq/137/smp_affinity <==
0020
==> /proc/irq/138/smp_affinity <==
...

CheckPoint рекомендует IRQ между сетевыми картами рекомендует делать такими, чтобы они не пересекались (IRQ swizzling). Рекомендуют отключать Hyper-Threading.

https://downloads.checkpoint.com/fileserver/SOURCE/direct/ID/7555/FILE/Performance_tests_methodology.pdf 
Hardware Configuration for Open Server
Interfaces that are constantly used should not share the same IRQ.
To prevent the use of the same IRQ in such a situation perform the following:
1. Upgrade BIOS to enable IRQ swizzling (for platforms that support this option).
IRQ swizzling is designed to enable PCI-E based NICs to have different IRQ pools. For
example, two PCI-E dual cards are put in two separate busses, they will both receive the same
IRQs (16 & 17 for example).
Upgrading the BIOS to include support for IRQ swizzling will enable the second NIC to have
different IRQs (18, 19 for example).
2. Select the ports that do not share the same IRQ for the heavily used network interfaces.
For example, configure the internal/external/sync subnets so that they will not share IRQ
interfaces.
3. Use gigabit based equipment (NICs, switches, cables)
4. Disable hyper-threading

 

Leave a Reply