cgroups não está funcionando corretamente com o aplicativo DPDK multi-core

1

Eu quero restringir o uso da CPU de um aplicativo DPDK para teste. Depois de uma pesquisa rápida, descobri que os grupos de controle (cgroups) podem atender às minhas necessidades. Então, primeiro instalei cgroup-bin .

sudo apt-get install cgroup-bin

Em seguida, criei um subsistema criando um diretório em /sys/fs/cgroup/cpu .

mkdir -v /sys/fs/cgroup/cpu/dpdk

Em seguida, escrevo minhas restrições ao uso da CPU para cpu.cfs_period_us e cpu.cfs_quota_us . Por exemplo, eu quero restringir o uso da CPU do meu aplicativo DPDK em 30%.

cd /sys/fs/cgroup/cpu/dpdk
echo 1000000 > cpu.cfs_period_us
echo 300000 > cpu.cfs_quota_us

Essa abordagem funciona ao executar aplicativos DPDK que usam apenas um núcleo. Por exemplo, o aplicativo de amostra de encaminhamento básico em 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

Eu posso ver em top que o uso de CPU do basicfwd está na verdade em 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 

No entanto, quando executo um aplicativo DPDK que usa mais de um núcleo. O resultado é um pouco estranho. Por exemplo, quero executar o aplicativo de amostra de encaminhamento L3 em 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

Quando abro top , vejo que o uso da CPU de l3fwd está em 130%, em vez de 30%, o que eu esperava.

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  

Parece que as restrições são aplicadas a apenas um núcleo. No entanto, em esta página , diz-se que a quota e os parâmetros de período operam com base na CPU

cpu.cfs_quota_us

specifies the total amount of time in microseconds (µs, represented here as "us") for which all tasks in a cgroup can run during one period (as defined by cpu.cfs_period_us). As soon as tasks in a cgroup use up all the time specified by the quota, they are throttled for the remainder of the time specified by the period and not allowed to run until the next period. If tasks in a cgroup should be able to access a single CPU for 0.2 seconds out of every 1 second, set cpu.cfs_quota_us to 200000 and cpu.cfs_period_us to 1000000. Note that the quota and period parameters operate on a CPU basis. To allow a process to fully utilize two CPUs, for example, set cpu.cfs_quota_us to 200000 and cpu.cfs_period_us to 100000.

O que estou perdendo aqui? O que devo fazer para restringir o uso da CPU de um aplicativo DPDK de vários núcleos a menos de 100%?

    
por B. Wang 28.02.2017 / 05:31

1 resposta

1

TL; DR:

  • use for i in $(pgrep -w l3fwd); do echo $i > tasks; done

Detalhes:

Eu acho que no seu caso, o pgrep para atribuição de tarefa precisa de alguma melhoria para trabalhar com vários IDs sendo relatados.

Se ele retorna um PID, as coisas funcionam bem, mas se ele retornar mais, a interface do cgroup realmente reporta

pgrep: write error: Invalid argument

Talvez você tenha apenas simplificado seu relatório, mas verifique se todas as tarefas estão no arquivo de tarefas cgroups e use um loop (ou qualquer outra alternativa).

$ stress-ng -c 4
$ for i in $(pgrep stress); do echo $i > /sys/fs/cgroup/cpu/dpdk/tasks; done
$ cat tasks 
28543
28544
[...]

Agora, para o seu caso em particular, o l3fwd tem um processo, mas três threads. Então, pgrep só informará o pid principal, os outros (loops principais) serão irrestritos. Você pode ver quando criar e testar por meio de ps axlf vs ps -eLf e a pgrep output.

. /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

Então você precisa pegar pgrep -w e combiná-lo com o acima.

for i in $(pgrep -w l3fwd); do echo $i > tasks; done

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

para

  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 

Ainda assim, por favor, veja meu comentário inicial, exceto para experiências, por favor, para não limitar o consumo de CPU do DPDK - então, em vez disso, não use DPDK.

    
por Christian Ehrhardt 20.03.2017 / 13:03