J'essaie de déplacer toutes les interruptions sur les noyaux 0-3 pour garder le reste de mes cœurs libres pour une virtualisation à grande vitesse et à faible latence.
J'ai écrit un script rapide pour définir l'affinité IRQ à 0-3:
#!/bin/bash
while IFS= read -r LINE; do
echo "0-3 -> \"$LINE\""
Sudo bash -c "echo 0-3 > \"$LINE\""
done <<< "$(find /proc/irq/ -name smp_affinity_list)"
Cela semble fonctionner pour des périphériques USB et des périphériques réseau, mais pas des périphériques NVME. Ils produisent tous cette erreur:
bash: line 1: echo: write error: Input/output error
Et ils continuent obstinément à produire des interruptions uniformément à travers presque tous mes cœurs.
Si je vérifie les affinités actuelles de ces appareils:
$ cat /proc/irq/81/smp_affinity_list
0-1,16-17
$ cat /proc/irq/82/smp_affinity_list
2-3,18-19
$ cat /proc/irq/83/smp_affinity_list
4-5,20-21
$ cat /proc/irq/84/smp_affinity_list
6-7,22-23
...
Il semble "quelque chose" prend pleinement le contrôle de la propagation des IRQ à travers les noyaux et de ne pas me laisser changer.
Il est complètement critique que je les déplace vers d'autres cœurs, car je fais lourd IO dans des machines virtuelles sur ces cœurs et les lecteurs NVME produisent une charge de merde d'interruptions. Ce n'est pas Windows, je suis censé pouvoir décider de ce que fait ma machine.
Qu'est-ce qui contrôle l'affinité IRQ pour ces appareils et comment puis-je le remplacer?
J'utilise un processeur Ryzen 3950x sur une carte mère de Gigabyte Auros X570 avec 3 lecteurs NVME connectés aux ports M.2 de la carte mère.
(Mise à jour: J'utilise maintenant un 5950X, toujours au même problème)
Noyau: 5.12.2-Arch1-1
Sortie de lspci -v
liée à NVME:
01:00.0 Non-Volatile memory controller: Phison Electronics Corporation E12 NVMe Controller (rev 01) (prog-if 02 [NVM Express])
Subsystem: Phison Electronics Corporation E12 NVMe Controller
Flags: bus master, fast devsel, latency 0, IRQ 45, NUMA node 0, IOMMU group 14
Memory at fc100000 (64-bit, non-prefetchable) [size=16K]
Capabilities: [80] Express Endpoint, MSI 00
Capabilities: [d0] MSI-X: Enable+ Count=9 Masked-
Capabilities: [e0] MSI: Enable- Count=1/8 Maskable- 64bit+
Capabilities: [f8] Power Management version 3
Capabilities: [100] Latency Tolerance Reporting
Capabilities: [110] L1 PM Substates
Capabilities: [128] Alternative Routing-ID Interpretation (ARI)
Capabilities: [200] Advanced Error Reporting
Capabilities: [300] Secondary PCI Express
Kernel driver in use: nvme
04:00.0 Non-Volatile memory controller: Phison Electronics Corporation E12 NVMe Controller (rev 01) (prog-if 02 [NVM Express])
Subsystem: Phison Electronics Corporation E12 NVMe Controller
Flags: bus master, fast devsel, latency 0, IRQ 24, NUMA node 0, IOMMU group 25
Memory at fbd00000 (64-bit, non-prefetchable) [size=16K]
Capabilities: [80] Express Endpoint, MSI 00
Capabilities: [d0] MSI-X: Enable+ Count=9 Masked-
Capabilities: [e0] MSI: Enable- Count=1/8 Maskable- 64bit+
Capabilities: [f8] Power Management version 3
Capabilities: [100] Latency Tolerance Reporting
Capabilities: [110] L1 PM Substates
Capabilities: [128] Alternative Routing-ID Interpretation (ARI)
Capabilities: [200] Advanced Error Reporting
Capabilities: [300] Secondary PCI Express
Kernel driver in use: nvme
05:00.0 Non-Volatile memory controller: Phison Electronics Corporation E12 NVMe Controller (rev 01) (prog-if 02 [NVM Express])
Subsystem: Phison Electronics Corporation E12 NVMe Controller
Flags: bus master, fast devsel, latency 0, IRQ 40, NUMA node 0, IOMMU group 26
Memory at fbc00000 (64-bit, non-prefetchable) [size=16K]
Capabilities: [80] Express Endpoint, MSI 00
Capabilities: [d0] MSI-X: Enable+ Count=9 Masked-
Capabilities: [e0] MSI: Enable- Count=1/8 Maskable- 64bit+
Capabilities: [f8] Power Management version 3
Capabilities: [100] Latency Tolerance Reporting
Capabilities: [110] L1 PM Substates
Capabilities: [128] Alternative Routing-ID Interpretation (ARI)
Capabilities: [200] Advanced Error Reporting
Capabilities: [300] Secondary PCI Express
Kernel driver in use: nvme
$ dmesg | grep -i nvme
[ 2.042888] nvme nvme0: pci function 0000:01:00.0
[ 2.042912] nvme nvme1: pci function 0000:04:00.0
[ 2.042941] nvme nvme2: pci function 0000:05:00.0
[ 2.048103] nvme nvme0: missing or invalid SUBNQN field.
[ 2.048109] nvme nvme2: missing or invalid SUBNQN field.
[ 2.048109] nvme nvme1: missing or invalid SUBNQN field.
[ 2.048112] nvme nvme0: Shutdown timeout set to 10 seconds
[ 2.048120] nvme nvme1: Shutdown timeout set to 10 seconds
[ 2.048127] nvme nvme2: Shutdown timeout set to 10 seconds
[ 2.049578] nvme nvme0: 8/0/0 default/read/poll queues
[ 2.049668] nvme nvme1: 8/0/0 default/read/poll queues
[ 2.049716] nvme nvme2: 8/0/0 default/read/poll queues
[ 2.051211] nvme1n1: p1
[ 2.051260] nvme2n1: p1
[ 2.051577] nvme0n1: p1 p2
Qu'est-ce qui contrôle l'affinité IRQ pour ces appareils?
Le noyau Linux depuis v4.8 utilise automatiquement MSI/MSI-X Masquage d'interruption dans les pilotes NVME; et avec IRQD_AFFINITY_MANAGED
, gère automatiquement les interruptions MSI/MSI-X dans le noyau.
Voir ces engagements:
90c9712fbb388077b5e53069cae43f1acbb0102a
- NVME: utilisez toujours des interruptions MSI/MSI-X9c2555835bb3d34dfac52a0be943dcc4bedd650f
- Genirq: introduire IRQD_AFFINITY_MANAGED
drapeauVoir votre version de noyau et vos capacités de vos appareils via lspci -v
Sortie, apparemment c'est le cas.
et comment puis-je le remplacer?
En plus de désactiver les drapeaux et de recompiler le noyau, désactivez probablement MSI/MSI-X à votre pont PCI (au lieu d'appareils):
echo 1 > /sys/bus/pci/devices/$bridge/msi_bus
Notez qu'il y aura un impact sur la performance sur la désactivation de MSI/MSI-X. Voir cette documentation de noya pour plus de détails.
Au lieu de désactiver MSI/MSI-X, une meilleure approche consisterait à garder le MSI-X mais permettrait également du mode de vote dans le pilote NVME. Voir Réponse d'Andrew H .
La solution la plus simple à ce problème est probablement simplement de passer de l'utilisation d'un mode IRQ/interruption au mode de vote du pilote NVME.
Ajoutez ceci à /etc/modprobe.d/nvme.conf
:
options nvme poll_queues=4
puis courez update-initramfs -u
, redémarrez et vous devriez voir une vaste réduction des IRQ pour les périphériques NVME. Vous pouvez également jouer avec le nombre de files d'attente de sondage dans SYSFS et d'autres Tweakables de pilote NVME (modinfo NVMe
devrait vous donner une liste de paramètres que vous pouvez ajuster)
Cela dit, il est tout fortement dépendant de la version du noyau que vous utilisez ...
C'est intentionnel.
Les périphériques NVME sont censés avoir plusieurs files d'attente de commande avec des interruptions associées. Les interruptions peuvent donc être livrées à la CPU qui demandaient l'opération.
Pour un disque virtuel émulé, il s'agit de la CPU exécutant le fil d'E/S, qui décide ensuite si la CPU VM doit être interrompue pour délivrer l'interruption émulée.
Pour un disque PCIe passthrough, il s'agit de la CPU VM, qui quitte la machine virtuelle, entre le gestionnaire d'interruptions d'hôte, qui remarque que l'interruption est destinée à la CPU virtuelle et en faisait donc la livraison à la VM sur le VM Entrez après le retour du gestionnaire, nous n'avons donc toujours qu'une interruption du contexte VM.
Ceci est à peu près aussi optimal que possible. Vous pouvez le pessimiser en fournissant l'IRQ à un autre processeur qui remarquera alors que le VM doit être interrompu et la file d'attente d'une interruption inter-processeur pour le diriger là où elle doit aller.
Pour les E/S qui n'appartiennent pas à une machine virtuelle, l'interruption devrait accéder à une CPU qui n'est pas associée à un VM.
Pour que cela fonctionne correctement, la cartographie de la CPU pour le VMS doit être un peu statique.
Il y a aussi le cadre isolation de la CP Cadre que vous pourriez jeter un coup d'œil, mais c'est probablement trop lourd.