GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Wie kann man eine CPU vor dem Linux-Scheduler abschirmen (verhindern, dass Threads auf dieser CPU geplant werden)?

Die Antwort ist die Verwendung von CPU-Sets. Das Dienstprogramm python cpuset macht es einfach, sie zu konfigurieren.

Grundkonzepte

3 CPU-Sätze

  • root :in allen Konfigurationen vorhanden und enthält alle CPUs (ungeschirmt )
  • system :enthält CPUs, die für Systemaufgaben verwendet werden - diejenigen, die ausgeführt werden müssen, aber nicht "wichtig" sind (unshielded )
  • user :enthält CPUs, die für "wichtige" Aufgaben verwendet werden - diejenigen, die wir im "Echtzeit"-Modus ausführen möchten (abgeschirmt )

Die shield Befehl verwaltet diese 3 CPU-Sets.

Während des Setups verschiebt es alle beweglichen Tasks in den ungeschirmten CPU-Satz (system ) und verschiebt beim Teardown alle beweglichen Tasks in den root cpuset.Nach der Einrichtung können Sie mit dem Unterbefehl Aufgaben in das Schild verschieben (user ) cpuset und zusätzlich spezielle Tasks (Kernel-Threads) von root zu verschieben bis system (und damit aus dem user CPU-Satz).

Befehle:

Zuerst erstellen wir einen Schild. Natürlich ist das Layout des Schildes maschinen-/aufgabenabhängig. Angenommen, wir haben einen Nicht-NUMA-Computer mit 4 Kernen:Wir möchten dem Schild 3 Kerne widmen , und lassen Sie 1 Kern für unwichtige Aufgaben übrig; Da es sich nicht um NUMA handelt, müssen wir keine Speicherknotenparameter angeben, und wir lassen die Kernel-Threads in root laufen cpuset (also:über alle CPUs hinweg)

$ cset shield --cpu 1-3

Einige Kernel-Threads (solche, die nicht an bestimmte CPUs gebunden sind) können in den system verschoben werden CPU-Satz. (Im Allgemeinen ist es keine gute Idee, Kernel-Threads zu verschieben, die an eine bestimmte CPU gebunden sind)

$ cset shield --kthread on

Lassen Sie uns nun auflisten, was im Shield läuft (user ) oder ungeschirmt (system ) CPU-Sätze:(-v für verbose, das die Prozessnamen auflistet) (fügen Sie ein zweites -v hinzu um mehr als 80 Zeichen anzuzeigen)

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

Wenn wir den Schild stoppen wollen (Teardown)

$ cset shield --reset

Lassen Sie uns nun einen Prozess im Schild ausführen (Befehle nach '--' werden an den auszuführenden Befehl übergeben, nicht an cset )

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

Wenn wir bereits einen laufenden Prozess haben, den wir in den Schild verschieben möchten (beachten Sie, dass wir mehrere Prozesse verschieben können, indem wir eine durch Kommas getrennte Liste oder Bereiche übergeben (jeder Prozess im Bereich wird verschoben, auch wenn es Lücken gibt))

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

Erweiterte Konzepte

cset set/proc - Diese geben Ihnen eine feinere Kontrolle über CPU-Sets

Einstellen

CPU-Sets erstellen, anpassen, umbenennen, verschieben und zerstören

Befehle

Erstellen Sie einen CPU-Satz mit den CPUs 1-3, verwenden Sie den NUMA-Knoten 1 und nennen Sie ihn "my_cpuset1"

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

Ändern Sie "my_cpuset1", um nur die CPUs 1 und 3 zu verwenden

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

Einen CPU-Satz zerstören

$ cset set --destroy --set=my_cpuset1

Benennen Sie einen bestehenden CPU-Satz um

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

Erstellen Sie einen hierarchischen CPU-Satz

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

Vorhandene CPU-Sätze auflisten (Tiefe von Level 1)

$ cset set --list

Vorhandenes CPU-Set und seine Kinder auflisten

$ cset set --list --set=my_cpuset1

Alle existierenden CPU-Sets auflisten

$ cset set --list --recurse

Proc

Threads und Prozesse verwalten

Befehle

Aufgaben auflisten, die in einem CPU-Satz laufen

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

Eine Aufgabe in einem CPU-Set ausführen

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

Eine Aufgabe verschieben

$ 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

Eine Aufgabe und alle ihre Geschwister verschieben

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

Verschieben Sie alle Aufgaben von einem CPU-Satz zu einem anderen

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

Verschieben Sie unfixierte Kernel-Threads in einen CPU-Satz

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

Verschieben Sie Kernel-Threads (einschließlich derer, die an eine bestimmte CPU gepinnt sind) zwangsweise in einen CPU-Satz (Hinweis:Dies kann schwerwiegende Folgen für das System haben - stellen Sie sicher, dass Sie wissen, was Sie tun)

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

Hierarchiebeispiel

Wir können hierarchische CPU-Sätze verwenden, um priorisierte Gruppierungen zu erstellen

  1. Erstellen Sie einen system CPU-Set mit 1 CPU (0)
  2. Erstellen Sie einen prio_low CPU-Set mit 1 CPU (1)
  3. Erstellen Sie einen prio_met CPU-Set mit 2 CPUs (1-2)
  4. Erstellen Sie einen prio_high CPU-Set mit 3 CPUs (1-3)
  5. Erstellen Sie einen prio_all cpuset mit allen 4 CPUs (0-3) (beachten Sie, dass dies dasselbe wie root ist; es wird als gute Praxis angesehen, eine Trennung von root beizubehalten)

Um das Obige zu erreichen, erstellen Sie prio_all und dann eine Teilmenge prio_high unter prio_all usw.

$ 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

Es gibt zwei andere Möglichkeiten, die ich mir vorstellen kann (wenn auch nicht so elegant wie cset, das von Redhat nicht so fantastisch unterstützt zu werden scheint):

1) Taskset alles einschließlich PID 1 - nett und einfach (aber angeblich - ich habe selbst noch nie Probleme gesehen - kann zu Ineffizienzen im Scheduler führen). Das folgende Skript (das als root ausgeführt werden muss) führt taskset auf allen laufenden Prozessen aus, einschließlich init (PID 1); Dadurch werden alle laufenden Prozesse an einen oder mehrere „Junk-Kerne“ geheftet, und indem auch init gepinnt wird, wird sichergestellt, dass alle zukünftigen Prozesse ebenfalls in der Liste der „Junk-Kerne“ gestartet werden:

#!/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) Verwenden Sie den Kernel-Parameter isolcpus (hier ist die Dokumentation von 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.

Ich habe diese beiden plus die cset-Mechanismen für mehrere Projekte verwendet (übrigens bitte verzeihen Sie die offensichtliche Eigenwerbung :-)), ich habe gerade ein Patent für ein Tool namens Pontus Vision ThreadManager angemeldet, das optimale Pinning-Strategien für alle entwickelt gegebene x86-Plattform für beliebige gegebene Software-Arbeitslasten; Nachdem ich es an einem Kundenstandort getestet hatte, erzielte ich wirklich gute Ergebnisse (270 % Reduzierung der Spitzenlatenzen), daher lohnt es sich, Pinning und CPU-Isolierung durchzuführen.


Linux
  1. So durchsuchen Sie das Web vom Terminal unter Linux

  2. So finden Sie das Paket, das eine bestimmte Datei in Linux bereitstellt

  3. Linux – Woher wissen Sie, dass die CPU 64-Bit-Betriebssysteme unter Linux unterstützt?

  4. Wie kann man verhindern, dass `ls` die Ausgabe sortiert?

  5. Wie verwende ich den Befehl linux flock, um zu verhindern, dass ein anderer Root-Prozess eine Datei löscht?

Wie der Linux-Kernel mit Interrupts umgeht

So installieren Sie die neueste OpenSSL-Version von Source unter Linux

So suchen Sie Dateien im Terminal unter Linux

So finden Sie die Anzahl der CPU-Kerne über die Befehlszeile in Linux

So erhalten Sie den Dateinamen aus dem vollständigen Pfad in Linux

So verbinden Sie sich vom Terminal in Ubuntu Linux mit WLAN