Linux: Assign Process to CPU Core

Objective: On SMP (Symmetric Multiprocessing) systems, override the Linux kernel’s process scheduling and bind a certain process to a specific CPU or core.

Binding a program or process to specific CPU cores can be beneficial in several scenarios. For example, the CPU cache is lost whenever a process is swapped to a different CPU core. But when the process is pinned to a specific CPU core, it will reduce CPU cache misses. This will help improve performance especially if the process has a high cache-bound workload. Also, when two processes communicate via shared memory intensively, scheduling both processes on the cores in the same NUMA domain would speed up their performance. Do take note that the Linux scheduler, by default, attempts to keep processes on the same CPU as long as practical for performance reasons.

On Linux, to assign particular CPU cores to a program or process, you can use taskset, a command line tool for retrieving or setting a process’ CPU affinity.

Install taskset on Linux

The taskset utility is part of the “util-linux” package in Linux. Most Linux distributions come with the package pre-installed by default. If taskset is not available on your Linux system, install it using apt-get (Debian based) or yum (RedHat based) depending on your flavuor of Linux.

$ sudo apt-get install util-linux 
$ sudo yum install util-linux 

Retrieve CPU Affinity of Running Process

If a process is already running and if you want to retrieve the CPU affinity properties of the process, use taskset in the following format.

# taskset -p <pid> 

If for example, to check the CPU affinity of a process with PID 5504, use the following syntax.

# taskset -p 5504
pid 5504's current affinity mask: f

The CPU affinity is represented as a bitmask, with the lowest order bit corresponding to the first logical CPU and the highest order bit corresponding to the last logical CPU. In the example above, the CPU affinity is printed out in hexadecimal as 0x0f. In binary, it will be ‘00001111’. This means that the process can run in 4 different CPU cores (from 0 to 3).

If you find the bitmask confusing, you can get taskset to print a numerical list of processors instead of the bitmask by using the following syntax.

# taskset -cp 5504
pid 5504's current affinity mask: 0-3

Set CPU Affinity of Running Process

To assign the CPU cores for a process, use one of the following formats. The first is using bitmask, the second is using processor list.

# taskset -p <bitmask> <pid> 
# taskset -cp <cpu-list> <pid> 

To assign PID 5504 to CPU cores 0 and 3, using bitmask, use the following syntax.

# taskset -p 0x09 5504
pid 5504's current affinity mask: f
pid 5504's new affinity mask: 9

To specify processor list, use the following syntax.

# taskset -cp 0,3 5504
pid 5504's current affinity mask: 0-3
pid 5504's new affinity mask: 0,3

Launch a Process on Specific CPU Cores

To launch a process and “bond” the process to a specific set of CPU cores, use one of the two formats below.

# taskset -p <bitmask> /path/to/program
# taskset -cp <cpu-list> /path/to/program

Dedicate / Restrict CPU Core to Process

Even if you assign CPU cores to a process using taskset, it does not mean the assigned CPU cores will not be used to run other processes. The Linux scheduler will use all CPU cores for scheduling tasks. To prevent the Linux scheduler from scheduling any user-space threads on a CPU core, the “isolcpus” kernel boot parameter has to be used to isolate the CPU core.

Once a CPU core is isolated, the Linux scheduler will not use the CPU core to run any user-space processes. The isolated CPUs will not participate in load balancing, and will not have tasks running on them unless explicitly assigned. You can manually assign processes to be run on the isolated CPU cores using taskset.

To isolate the 1st and 3rd CPU cores (CPU numbers start from 0) on your system, add the following to the kernel command line during boot:

isolcpus=1,3

If you are on GRUB2, and if you want to make the entries permanent, modify the value of GRUB_CMDLINE_LINUX parameter in the /etc/default/grub file.

ibrahim = { interested_in(unix, linux, android, open_source, reverse_engineering); coding(c, shell, php, python, java, javascript, nodejs, react, vuejs); plays_on(xbox, ps4); linux_desktop_user(true); }