How to Configure CPU Usage on Torizon OS
Introduction
This how-to article aims to help you with techniques to limit the CPU usage and/or to isolate CPU cores in the context of containers, guiding you through the steps that you need to perform.
How to discover the SoC’s CPU number
Enter in your board’s terminal via SSH or serial terminal (debug UART). To learn how to use SSH, refer to Establishing an SSH Connection. To learn how to use the debug UART console, refer to Use the Debug UART (Serial Console).
Go to
/sys/devices/system/cpu
folder.
# cd /sys/devices/system/cpu
- List the directory and find how many CPUs are there in your SoM. For example, for Apalis iMX8QM you can see that it has 6 CPUs, numbered from 0 to 5.
# ls
consumers cpu2 cpu5 hotplug modalias possible smt vulnerabilities
cpu0 cpu3 cpufreq isolated offline power suppliers
cpu1 cpu4 cpuidle kernel_max online present uevent
- To discover how the CPUs are ordinated in your system, print the content of the file
core_siblings_list
insidecpu<i>/topology/
folder. For Apalis iMX8QM, you must iterate from 0 to 5 because, as saw in the previous step, CPUs are numbered from 0 to 5.
# for i in {0..5}; do cat ./cpu$i/topology/core_siblings_list; done
0-3
0-3
0-3
0-3
4-5
4-5
As you can see, the iMX8QM has two different groups of CPUs. CPUs 0 to 3 are part of the same group, as do CPUs 4 and 5.
- Refer to your SoMs datasheet to find out what each core is. For Apalis iMX8QM, you can find that it has 4 A53 cores and 2 A72 cores. Therefore, it is concluded that cores 0 to 3 are A53, and 4 and 5, A72.
How to set CPU limits
Quoting Docker Documentation:
The CFS is the Linux kernel CPU scheduler for normal Linux processes. Several runtime flags allow you to configure the amount of access to CPU resources your container has. When you use these settings, Docker modifies the settings for the container’s cgroup on the host machine.
When it comes to setting CPU limits and/or isolating CPU cores, the two most important options of the docker run
command are the following ones:
Option | Description |
---|---|
--cpus=<value> | Specify how much of the available CPU resources a container can use. For example, --cpus=0.5 to limit to half of the capacity or --cpus=1.5 , in case of a dual core SoC (150% of the combined 200% CPU capacity, i.e. 75% of the total capcity). |
--cpuset-cpus | Limit the specific CPUs or cores a container can use. The value should be a list of CPU numbers separated by commas 0,1 or a defined range 0-2 . |
To use the mentioned parameters to limit the CPU usage or isolate CPUs, launch the container the following way, using both or just one of the options
# docker run --cpus="<value>" --cpuset-cpus <cpus> <dockerhub_username>/<container>
Multiple CPUs can be specified. This command will assign the Docker Container to CPU 0 and 1:
# docker run --cpuset-cpus 0,1 <dockerhub_username>/<container>
A range of CPUs can be specified. This command will assign the Docker Container to CPU 0 through 3:
# docker run --cpuset-cpus 0-3 <dockerhub_username>/<container>
As well, you can limit to half of the CPU capacity, for example
# docker run ---cpus=".5" <dockerhub_username>/<container>
For more information about the parameters and ways to limit CPU cores, refer to Runtime options with Memory, CPUs, and GPUs .
Example
Stress Test Container
Follow the next steps to create and build a container that is able to stress 100% of the available CPU.
The first step is to build a container with a workload generator that imposes a configurable amount of stress on the system. A great example of this is the stress
application. Follow the next steps to create and build a container that is able to stress the CPU.
Create a Dockerfile based on a Debian Docker image provided by Toradex at github.
Install the
stress
application in theRUN
command.Add an
ENTRYPOINT
to the Dockerfile that calls the stress application in--verbose
mode.
The Dockerfile should look like this:
ARG IMAGE_ARCH=linux/arm
# For arm64v8 use:
# ARG IMAGE_ARCH=linux/arm64/v8
FROM torizon/debian:3-bookworm AS base
RUN apt-get update && apt-get install -y stress && rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["/usr/bin/stress", "--verbose"]
- Build the container with the desired tag. Select the your SoM from the tabs below.
$ docker build --build-arg IMAGE_ARCH=linux/arm64/v8 -t <dockerhub_username>/stress .
$ docker build -t <dockerhub_username>/stress .
- Push it to your docker-hub repository:
$ docker push <dockerhub_username>/stress
Run the Stress Test
- Open the terminal of your board and then launch the container. As you can see, this command allows the stress of the 6 cpus at the same time. However, let’s limit the container to use core 0 and 1.
# docker run -it --cpuset-cpus 0,1 <dockerhub_username>/stress --cpu 6
stress: info: [1] dispatching hogs: 6 cpu, 0 io, 0 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 18000us
stress: dbug: [1] --> hogcpu worker 6 [7] forked
stress: dbug: [1] using backoff sleep of 15000us
stress: dbug: [1] --> hogcpu worker 5 [8] forked
stress: dbug: [1] using backoff sleep of 12000us
stress: dbug: [1] --> hogcpu worker 4 [9] forked
stress: dbug: [1] using backoff sleep of 9000us
stress: dbug: [1] --> hogcpu worker 3 [10] forked
stress: dbug: [1] using backoff sleep of 6000us
stress: dbug: [1] --> hogcpu worker 2 [11] forked
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogcpu worker 1 [12] forked
- Open another terminal and launch
htop
. You should see something like this:
- Let’s load just 75% of the CPUs 2 and 5, stressing the A53 and A72 cores.
# docker run -it --cpuset-cpus 2,5 --cpus="1.5" <dockerhub_username>/stress --cpu 6
stress: info: [1] dispatching hogs: 6 cpu, 0 io, 0 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 18000us
stress: dbug: [1] --> hogcpu worker 6 [6] forked
stress: dbug: [1] using backoff sleep of 15000us
stress: dbug: [1] --> hogcpu worker 5 [7] forked
stress: dbug: [1] using backoff sleep of 12000us
stress: dbug: [1] --> hogcpu worker 4 [8] forked
stress: dbug: [1] using backoff sleep of 9000us
stress: dbug: [1] --> hogcpu worker 3 [9] forked
stress: dbug: [1] using backoff sleep of 6000us
stress: dbug: [1] --> hogcpu worker 2 [10] forked
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogcpu worker 1 [11] forked
- At the htop terminal you should see something like this:
Docker-compose
You can also set CPU limits using a docker-compose file. Be aware that the options to limit the CPU may tweak the name. For instance, the option cpuset-cpus
becomes cpuset
. The docker-compose below shows a simple model you can use to configure the CPU limits for your container.
version: "<version_number>"
services:
<service-name>:
image: <dockerhub_username>/<container>
cpus: <cpu_resources>
cpuset: <cpu_numbers>
For the stress test example, the docker-compose file should look like the following one.
version: "2.4"
services:
stress:
image: <dockerhub_username>/stress
cpus: 0.5
cpuset: 0,1
command: --cpus 6