GNU/Linux >> Linux Esercitazione >  >> Linux

come proteggere una cpu dallo scheduler di linux (impedire che pianifichi i thread su quella cpu)?

La risposta è usare cpusets. L'utility python cpuset semplifica la loro configurazione.

Concetti di base

3 set di cpu

  • root :presente in tutte le configurazioni e contiene tutte le cpu (unshielded )
  • system :contiene le cpus usate per le attività di sistema - quelle che devono essere eseguite ma non sono "importanti" (non schermate )
  • user :contiene le cpus usate per compiti "importanti" - quelli che vogliamo eseguire in modalità "tempo reale" (schermata )

Il shield command gestisce questi 3 cpusets.

Durante l'installazione sposta tutte le attività mobili nel cpuset non schermato (system ) e durante lo smontaggio sposta tutte le attività mobili nel root cpuset.Dopo la configurazione, il sottocomando ti consente di spostare le attività nello scudo (user ) cpuset e, inoltre, per spostare attività speciali (thread del kernel) da root a system (e quindi fuori dal user cpuset).

Comandi:

Per prima cosa creiamo uno scudo. Naturalmente il layout dello scudo dipenderà dalla macchina/attività. Ad esempio, supponiamo di avere una macchina non NUMA a 4 core:vogliamo dedicare 3 core allo shield e lascia 1 core per le attività non importanti; poiché non è NUMA, non abbiamo bisogno di specificare alcun parametro del nodo di memoria e lasciamo i thread del kernel in esecuzione nel root cpuset (ovvero:su tutte le cpu)

$ cset shield --cpu 1-3

Alcuni thread del kernel (quelli che non sono legati a specifiche cpus) possono essere spostati nel system cpuset. (In generale non è una buona idea spostare i thread del kernel che sono stati associati a una cpu specifica)

$ cset shield --kthread on

Ora elenchiamo cosa è in esecuzione nello shield (user ) o non schermato (system ) cpusets:(-v per verbose, che elencherà i nomi dei processi) (aggiungi un secondo -v per visualizzare più di 80 caratteri)

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

Se vogliamo fermare lo scudo (teardown)

$ cset shield --reset

Ora eseguiamo un processo nello shield (comandi che seguono '--' vengono passati al comando da eseguire, non a cset )

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

Se abbiamo già un processo in esecuzione che vogliamo spostare nello scudo (nota che possiamo spostare più processi passando un elenco separato da virgole o intervalli (qualsiasi processo nell'intervallo verrà spostato, anche se ci sono spazi vuoti))

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

Concetti avanzati

cset set/proc - questi ti danno un controllo più preciso dei cpusets

Imposta

Crea, regola, rinomina, sposta e distruggi cpusets

Comandi

Crea un cpuset, usando cpus 1-3, usa il nodo NUMA 1 e chiamalo "my_cpuset1"

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

Cambia "my_cpuset1" per usare solo cpus 1 e 3

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

Distruggi un cpuset

$ cset set --destroy --set=my_cpuset1

Rinomina un cpuset esistente

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

Crea un cpuset gerarchico

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

Elenca cpusets esistenti (profondità del livello 1)

$ cset set --list

Elenca il cpuset esistente e i suoi figli

$ cset set --list --set=my_cpuset1

Elenca tutti i cpusets esistenti

$ cset set --list --recurse

Elaborazione

Gestisci thread e processi

Comandi

Elenca le attività in esecuzione in un cpuset

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

Esegue un'attività in un cpuset

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

Spostare un'attività

$ 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

Spostare un'attività e tutti i suoi fratelli

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

Sposta tutte le attività da un cpuset all'altro

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

Sposta i thread del kernel sbloccati in un cpuset

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

Sposta forzatamente i thread del kernel (inclusi quelli che sono collegati a una cpu specifica) in un cpuset (nota:questo potrebbe avere conseguenze disastrose per il sistema - assicurati di sapere cosa stai facendo)

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

Esempio di gerarchia

Possiamo usare cpusets gerarchici per creare raggruppamenti con priorità

  1. Crea 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 cpu (1-2)
  4. Crea un prio_high cpuset con 3 cpu (1-3)
  5. Crea un prio_all cpuset con tutte e 4 le cpu (0-3) (si noti che è uguale a root; è considerata una buona pratica mantenere una separazione da root)

Per ottenere quanto sopra, crea prio_all, quindi crea il sottoinsieme prio_high sotto prio_all, ecc

$ 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

Ci sono altri due modi in cui posso pensare di farlo (anche se non così elegante come cset, che non sembra avere un fantastico livello di supporto da parte di Redhat):

1) Taskset tutto incluso PID 1 - bello e facile (ma, presumibilmente - non ho mai visto alcun problema da solo - potrebbe causare inefficienze nello scheduler). Lo script seguente (che deve essere eseguito come root) esegue taskset su tutti i processi in esecuzione, incluso init (pid 1); questo bloccherà tutti i processi in esecuzione su uno o più 'nunk core' e, bloccando anche init, assicurerà che tutti i processi futuri vengano avviati anche nell'elenco dei 'junk core':

#!/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) usa il parametro del kernel isolcpus (ecco la documentazione da 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.

Ho usato questi due più i meccanismi cset per diversi progetti (per inciso, scusate la palese autopromozione :-)), ho appena depositato un brevetto per uno strumento chiamato Pontus Vision ThreadManager che fornisce strategie di pinning ottimali per qualsiasi data piattaforma x86 a qualsiasi dato carico di lavoro software; dopo averlo testato presso il sito di un cliente, ho ottenuto ottimi risultati (riduzione del 270% delle latenze di picco), quindi vale la pena eseguire il pinning e l'isolamento della CPU.


Linux
  1. Linux:come sapere che la CPU supporta i sistemi operativi a 64 bit sotto Linux?

  2. Come impedire a `ls` di ordinare l'output?

  3. Come riavvio Linux (Ubuntu) dalla riga di comando?

  4. Come posso copiare una cartella dalla riga di comando di Linux?

  5. Come posso riservare un blocco di memoria dal kernel Linux?

Come il kernel Linux gestisce gli interrupt

Come installare l'ultima versione di OpenSSL da Source su Linux

Come cercare file dal Terminale su Linux

Come trovare il numero di core della CPU dalla riga di comando in Linux

Come ottenere il nome del file dal percorso completo in Linux

Come connettersi al WiFi dal terminale in Ubuntu Linux