GNU/Linux >> Tutoriales Linux >  >> Linux

¿Cómo proteger una CPU del programador de Linux (evitar que programe subprocesos en esa CPU)?

La respuesta es usar cpusets. La utilidad python cpuset facilita su configuración.

Conceptos básicos

3 juegos de CPU

  • root :presente en todas las configuraciones y contiene todas las cpus (sin blindaje )
  • system :contiene CPU utilizadas para tareas del sistema, las que deben ejecutarse pero no son "importantes" (sin blindaje )
  • user :contiene CPU usadas para tareas "importantes" - las que queremos ejecutar en modo "tiempo real" (blindadas )

El shield El comando administra estos 3 cpusets.

Durante la configuración, mueve todas las tareas móviles al conjunto de CPU sin blindaje (system ) y durante el desmontaje mueve todas las tareas móviles al root cpuset.Después de la configuración, el subcomando le permite mover tareas al escudo (user ) cpuset y, además, para mover tareas especiales (subprocesos del kernel) desde root a system (y por lo tanto fuera del user cpuset).

Comandos:

Primero creamos un escudo. Naturalmente, el diseño del escudo dependerá de la máquina/tarea. Por ejemplo, supongamos que tenemos una máquina no NUMA de 4 núcleos:queremos dedicar 3 núcleos al escudo y deja 1 núcleo para tareas sin importancia; dado que no es NUMA, no necesitamos especificar ningún parámetro de nodo de memoria, y dejamos los subprocesos del kernel ejecutándose en el root cpuset (es decir, en todas las CPU)

$ cset shield --cpu 1-3

Algunos subprocesos del kernel (aquellos que no están vinculados a un CPU específico) se pueden mover al system cpuset. (En general, no es una buena idea mover subprocesos del núcleo que se han vinculado a una CPU específica)

$ cset shield --kthread on

Ahora enumeremos lo que se está ejecutando en el escudo (user ) o sin blindaje (system ) cpusets:(-v para verbose, que enumerará los nombres de los procesos) (agregue un segundo -v para mostrar más de 80 caracteres)

$ cset shield --shield -v
$ cset shield --unshield -v -v

Si queremos detener el escudo (desmontaje)

$ cset shield --reset

Ahora vamos a ejecutar un proceso en el escudo (comandos después de '--' se pasan al comando a ejecutar, no a cset )

$ cset shield --exec mycommand -- -arg1 -arg2

Si ya tenemos un proceso en ejecución que queremos mover al escudo (tenga en cuenta que podemos mover varios procesos pasando una lista separada por comas o rangos (cualquier proceso en el rango se moverá, incluso si hay espacios))

$ cset shield --shield --pid 1234
$ cset shield --shield --pid 1234,1236
$ cset shield --shield --pid 1234,1237,1238-1240

Conceptos avanzados

cset set/proc - estos le dan un control más preciso de cpusets

Conjunto

Crear, ajustar, renombrar, mover y destruir cpusets

Comandos

Cree un cpuset, usando cpus 1-3, use el nodo NUMA 1 y llámelo "my_cpuset1"

$ cset set --cpu=1-3 --mem=1 --set=my_cpuset1

Cambie "my_cpuset1" para usar solo cpus 1 y 3

$ cset set --cpu=1,3 --mem=1 --set=my_cpuset1

Destruye un conjunto de CPU

$ cset set --destroy --set=my_cpuset1

Cambiar el nombre de un cpuset existente

$ cset set --set=my_cpuset1 --newname=your_cpuset1

Crear un cpuset jerárquico

$ cset set --cpu=3 --mem=1 --set=my_cpuset1/my_subset1

Enumere cpusets existentes (profundidad de nivel 1)

$ cset set --list

Lista cpuset existente y sus hijos

$ cset set --list --set=my_cpuset1

Listar todos los cpusets existentes

$ cset set --list --recurse

Proceso

Administrar hilos y procesos

Comandos

Lista de tareas que se ejecutan en un cpuset

$ cset proc --list --set=my_cpuset1 --verbose

Ejecutar una tarea en un cpuset

$ cset proc --set=my_cpuset1 --exec myApp -- --arg1 --arg2

Mover una tarea

$ cset proc --toset=my_cpuset1 --move --pid 1234
$ cset proc --toset=my_cpuset1 --move --pid 1234,1236
$ cset proc --toset=my_cpuset1 --move --pid 1238-1340

Mover una tarea y todas sus hermanas

$ cset proc --move --toset=my_cpuset1 --pid 1234 --threads

Mover todas las tareas de un cpuset a otro

$ cset proc --move --fromset=my_cpuset1 --toset=system

Mover subprocesos del kernel no anclados a un cpuset

$ cset proc --kthread --fromset=root --toset=system

Mueva a la fuerza los subprocesos del núcleo (incluidos los que están anclados a una CPU específica) a un conjunto de CPU (nota:esto puede tener consecuencias nefastas para el sistema; asegúrese de saber lo que está haciendo)

$ cset proc --kthread --fromset=root --toset=system --force

Ejemplo de jerarquía

Podemos usar cpusets jerárquicos para crear agrupaciones priorizadas

  1. Cree un system cpuset con 1 CPU (0)
  2. Crea un prio_low cpuset con 1 cpu (1)
  3. Crea un prio_met cpuset con 2 cpus (1-2)
  4. Crea un prio_high cpuset con 3 cpus (1-3)
  5. Crea un prio_all cpuset con las 4 cpus (0-3) (tenga en cuenta que esto es lo mismo que root; se considera una buena práctica mantener una separación de root)

Para lograr lo anterior, cree prio_all y luego cree un subconjunto prio_high en prio_all, etc.

$ cset set --cpu=0 --set=system
$ cset set --cpu=0-3 --set=prio_all
$ cset set --cpu=1-3 --set=/prio_all/prio_high
$ cset set --cpu=1-2 --set=/prio_all/prio_high/prio_med
$ cset set --cpu=1 --set=/prio_all/prio_high/prio_med/prio_low

Hay otras dos formas en las que puedo pensar en hacer esto (aunque no tan elegantes como cset, que no parece tener un fantástico nivel de soporte de Redhat):

1) Taskset todo, incluido el PID 1:agradable y fácil (pero, al parecer, nunca he visto ningún problema, puede causar ineficiencias en el programador). El siguiente script (que debe ejecutarse como root) ejecuta el conjunto de tareas en todos los procesos en ejecución, incluido init (pid 1); esto anclará todos los procesos en ejecución a uno o más 'núcleos basura' y, al anclar también init, garantizará que cualquier proceso futuro también se inicie en la lista de 'núcleos basura':

#!/bin/bash

if [[ -z $1 ]]; then
  printf "Usage: %s '<csv list of cores to set as junk in double quotes>'", $0
  exit -1;
fi

for i in `ps -eLfad |awk '{ print $4 } '|grep -v PID | xargs echo `; do 
   taskset -pc $1 $i;
done

2) use el parámetro del kernel isolcpus (aquí está la documentación de https://www.kernel.org/doc/Documentation/kernel-parameters.txt):

isolcpus=   [KNL,SMP] Isolate CPUs from the general scheduler.
            Format:
            <cpu number>,...,<cpu number>
            or
            <cpu number>-<cpu number>
            (must be a positive range in ascending order)
            or a mixture
            <cpu number>,...,<cpu number>-<cpu number>

        This option can be used to specify one or more CPUs
        to isolate from the general SMP balancing and scheduling
        algorithms. You can move a process onto or off an
        "isolated" CPU via the CPU affinity syscalls or cpuset.
        <cpu number> begins at 0 and the maximum value is
        "number of CPUs in system - 1".

        This option is the preferred way to isolate CPUs. The
        alternative -- manually setting the CPU mask of all
        tasks in the system -- can cause problems and
        suboptimal load balancer performance.

He usado estos dos más los mecanismos cset para varios proyectos (por cierto, disculpe la autopromoción descarada :-)), acabo de presentar una patente para una herramienta llamada Pontus Vision ThreadManager que presenta estrategias de fijación óptimas para cualquier plataforma x86 dada a cualquier carga de trabajo de software dada; después de probarlo en el sitio de un cliente, obtuve muy buenos resultados (reducción del 270 % en las latencias máximas), por lo que vale la pena fijarlo y aislar la CPU.


Linux
  1. Cómo buscar en la web desde la terminal en Linux

  2. Cómo encontrar el paquete que proporciona un archivo específico en Linux

  3. Linux:¿cómo saber si la CPU admite sistemas operativos de 64 bits en Linux?

  4. ¿Cómo evitar que `ls` ordene la salida?

  5. ¿Cómo calcular el uso de CPU de un proceso por PID en Linux desde C?

Cómo el kernel de Linux maneja las interrupciones

Cómo instalar la última versión de OpenSSL desde Source en Linux

Cómo buscar archivos desde la Terminal en Linux

Cómo encontrar el número de núcleos de CPU desde la línea de comandos en Linux

Cómo obtener el nombre de archivo de la ruta completa en Linux

Cómo conectarse a WiFi desde la terminal en Ubuntu Linux