Je souhaite restreindre l'utilisation du processeur d'une application DPDK pour les tests. Après quelques recherches rapides, j'ai trouvé que les groupes de contrôle (cgroups) pouvaient convenir à mes besoins. J'ai donc d'abord installé cgroup-bin
.
Sudo apt-get install cgroup-bin
Et puis j'ai créé un sous-système en créant un répertoire sous /sys/fs/cgroup/cpu
.
mkdir -v /sys/fs/cgroup/cpu/dpdk
Et puis j'écris mes restrictions d'utilisation du CPU à cpu.cfs_period_us
et cpu.cfs_quota_us
. Par exemple, je souhaite limiter l'utilisation du processeur de mon application DPDK à 30%.
cd /sys/fs/cgroup/cpu/dpdk
echo 1000000 > cpu.cfs_period_us
echo 300000 > cpu.cfs_quota_us
Cette approche fonctionne lors de l'exécution d'applications DPDK qui n'utilisent qu'un seul cœur. Par exemple, l'application exemple de transfert de base à examples/skeleton
cd /home/wang/dpdk-17.02/examples/skeleton
make
./build/basicfwd -c 1 -n 2
pgrep basicfwd > /sys/fs/cgroup/cpu/dpdk/tasks
Je peux voir dans top
que l'utilisation CPU de basicfwd est en fait à 30%.
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3346 root 20 0 4222472 3100 2780 R 30.0 0.0 0:56.35 basicfwd
Cependant, lorsque j'exécute une application DPDK qui utilise plus d'un cœur. Le résultat est un peu bizarre. Par exemple, je souhaite exécuter l'exemple d'application L3 forward à examples/l3fwd
.
cd /home/wang/dpdk-17.02/examples/l3fwd
make
./build/l3fwd -l 1,2 -n 2 -- -p 0x3 -P --config="(0,0,1),(1,0,2)" --parse-ptype
pgrep l3fwd > /sys/fs/cgroup/cpu/dpdk/tasks
Lorsque j'ouvre top
, je constate que l'utilisation du processeur de l3fwd
est à 130%, au lieu de 30%, ce à quoi je m'attendais.
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3404 root 20 0 4305752 5092 2728 R 130.3 0.0 0:25.98 l3fwd
Il semble que les restrictions ne s'appliquent qu'à un seul noyau. Cependant dans cette page il est dit que les paramètres de quota et de période fonctionnent sur une base CPU
cpu.cfs_quota_us
spécifie la durée totale en microsecondes (µs, représentée ici par "us") pendant laquelle toutes les tâches d'un groupe de contrôle peuvent s'exécuter pendant une période (définie par cpu.cfs_period_us). Dès que les tâches d'un groupe de contrôle utilisent tout le temps spécifié par le quota, elles sont limitées pour le reste du temps spécifié par la période et ne sont pas autorisées à s'exécuter jusqu'à la période suivante. Si les tâches d'un groupe de contrôle doivent pouvoir accéder à un seul processeur pendant 0,2 seconde toutes les 1 seconde, définissez cpu.cfs_quota_us sur 200000 et cpu.cfs_period_us sur 1000000. Notez que les paramètres de quota et de période fonctionnent sur la base du processeur. Pour permettre à un processus d'utiliser pleinement deux CPU, par exemple, définissez cpu.cfs_quota_us sur 200000 et cpu.cfs_period_us sur 100000.
Qu'est-ce que j'oublie ici? Que dois-je faire pour limiter l'utilisation du processeur d'une application DPDK multicœur à moins de 100%?
TL; DR:
for i in $(pgrep -w l3fwd); do echo $i > tasks; done
Détails:
Je pense que dans votre cas, l'affectation de pgrep à la tâche doit être améliorée pour fonctionner avec plusieurs ID signalés.
S'il retourne un PID, les choses fonctionnent très bien, mais s'il renvoie plus, l'interface cgroup signale réellement
pgrep: write error: Invalid argument
Vous avez peut-être simplement simplifié votre rapport, mais veuillez vérifier que toutes les tâches se trouvent dans le fichier de tâches cgroups et utiliser une boucle (ou toute autre solution de contournement).
$ stress-ng -c 4
$ for i in $(pgrep stress); do echo $i > /sys/fs/cgroup/cpu/dpdk/tasks; done
$ cat tasks
28543
28544
[...]
Maintenant pour votre cas en particulier, l3fwd a un processus mais trois threads. Ainsi, pgrep
ne rapportera que le pid principal, les autres (boucles principales) sont sans restriction. Vous pouvez voir quand vous le générez et le testez via ps axlf
contre ps -eLf
et la sortie pgrep
.
. /usr/share/dpdk/dpdk-sdk-env.sh
mkdir -p l3fwd
make -C /usr/share/dpdk/examples/l3fwd "O=$(pwd)/l3fwd/"
# config /etc/dpdk/dpdk.conf and /etc/dpdk/interfaces
service dpdk restart
$(pwd)/l3fwd/l3fwd -l 1,2 --socket-mem 512 -- -p 0x3 -P --config="(0,0,1),(1,0,2)" --parse-ptype
Vous devez donc prendre pgrep -w
et combinez-le avec ce qui précède.
for i in $(pgrep -w l3fwd); do echo $i > tasks; done
Et e voila, de:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
29849 root 20 0 703052 4184 3336 R 200,7 0,0 0:17.36 l3fwd
à
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
29849 root 20 0 703052 4184 3336 R 29,8 0,0 0:34.11 l3fwd
Veuillez toujours voir mon commentaire initial, sauf pour les expériences, veuillez ne pas limiter la consommation du processeur DPDK - alors n'utilisez simplement pas DPDK.