6 Dec 2012

How to Change CPU Affinity of CPU Intensive Multithreaded Applications (Ubuntu)

When you use CPU intensive, multithreaded software tools on your multicore-processor such as 'pigz' or 'pbzip2' (for example), the OS loses its responsiveness (more or less) and it will slow down other running tasks, and it is something that should be expected too.

Changing CPU affinity using Htop - example
Changing CPU affinity using Htop - example
However, when running such applications while performing your other daily computer related tasks, the degraded OS responsiveness can become an issue. For instance, the movement of the mouse might not be that smooth any more, or if you click on another application, then it won't be opened as fast as before etc.

Tools like 'pbzip2' lets you manually change the threads to be used, before the execution, so you can free-up a CPU core or two, thus improving the OS's responsiveness. But sometimes, I forget do that, plus, not all multithreaded tools let you change the number of threads to be used either.

Now as most knows, in these occasions, the feature called CPU affinity comes in handy, as it lets us bind a process in a way, that it will be executed by using only a certain number of CPU cores (supports changing the CPU cores that should be used even after the process is running from the background).



So what I usually do is, I manually reduce the number of available cores for the processor intensive multithreaded utility, and as soon as I do that, the OS's responsiveness comes back.

Unlike in Windows, the system monitor utility in Ubuntu does not support it, and I use, another two built in tools that come pre-installed with Ubuntu for that. So I thought, writing a simple 'how to' guide might come in handy for someone who is new to GNU/Linux.
But please remember that, reducing available CPU cores for multithreaded applications will decrease their performance (obviosusly).
For this example, I'm using 'bpzip2' as the utility that I want to change the CPU affinity, but of course, you can do this to any utility, by simply following the below steps.

In Ubuntu, the most easiest way to do this is to use 'Htop' (shown in the first screenshot) as it comes with somewhat a user friendly interface, also supports the mouse thus, you can basically track down the process from its interface and also change the affinity directly through there.

But, changing processor affinity for multithreaded processes is a bit hectic under 'Htop', as you will have to change the affinity value of each thread, manually.

Luckily, as mentioned above, by using two command-line tools, we can can achieve the same task extremely easily (I also assume that you are trying to do this when the multithreaded app is already running from the background).

The first tool is called 'top', which is nothing but a simple process monitor. And the other is called 'taskset' which lets us change the CPU affinity value.  

Let's do it ...

Before changing the CPU affinity of a process, first we need to find the 'id' of that particular process (PID)'. Once that is retrieved, the rest is extremely simple, and all it requires is a single command.

Step 1: Finding the 'Process ID'

Assuming that 'pbzip2' is running, consuming almost all of my CPU power, and I want to make it only use 3 CPU cores, then as said above, I need to find its 'process id' first. So, I open your Terminal and enter the below command.
top -d 1
'-d 1' is optional (it just sets the update interval to a second). Now, because these are CPU intensive tools, they should be listed at the top of the process list in 'top', which makes locating them a breeze (even if you don't know its exact name).

In 'top', you can see the running processes and their names under the 'COMMAND' field, and their 'process id' under 'PID' field. As for this example, as highlighted below, my utility is listed as 'pbzip2' and its process id is '5964'.  

Finding the 'process id' and process name using 'top'
Finding the 'process id' and process name using 'top'

Step 2: 'Binding' the process to a certain CPU core (s).

As soon as I got its 'PID', then I can use 'taskset' tool to change the CPU affinity value.

I can close the 'top' utility (by pressing keyboard shortcut 'q') and use its Terminal window or, can open a new window and simply enters the below command, to get the job done.
taskset -pac 0,1,2 5964
'taskset' running in Ubuntu 12.10
That's it!

Simple explanation of the above command ...  

*. 'taskset' is the utility that does this job and '-pac' are its command-line arguments that enable few of its built in options.  

*. The 'p' option lets us use 'process id' of a program for changing the CPU affinity value.

*. The 'a' option' enables applying the user requested changes to all of the threads of that particular program, so unlike with 'Htop', we do not have to set it in each thread, individually.

 *. The 'c' option is used for entering the CPU cores that we are going to bind that program with, which is followed by the numbers '0,1,2' (there is a comma that separates each core number).

As a general rule, the first CPU core is represented by 0 (zero), second one is called 1, third one is called 2 etc.


Note: If you don't know how many cores your CPU has, then simply enter the below command and from its text output, take a note of the number under the option called 'CPU( S ) :'. This number lists the total CPU core that you have.
lscpu
(4 in this example. It is 2 cores actually, but because they are multithreaded, they appear as 4 cores).  

Using 'lscpu' to get certain CPU related details in Ubuntu
Using 'lscpu' to get certain CPU related details in Ubuntu
For example, let's say that you have 8 cores and would like to bind a process only to the first 6 cores. Then use the 'taskset' command in the below format.
taskset -pac 0,1,2,3,4,5 process-id



*. Lastly, the number '5964', is the ID of the process that we want to hunt down ;-).

As soon 'taskset' changes the CPU affinity, through the Terminal it gave me an output (shown below), that lists the threads of 'pbzip2' and their old and new CPU affinity values.

'taskset' showing the old and new CPU affinity values
'taskset' showing the old and new CPU affinity values
Note: As mentioned, this is an example, so make sure to replace the CPU core numbers and 'process id' according to the utility that you are using.
And now I can confirm whether this has worked or not, by using the built in graphical system monitor or using the 'top' utility. For this example, under CPU usage, you should see that, except for the fourth core, all others are occupied by 'pbzip2'.  

'pbzip2' running without using the CPU core 4
'pbzip2' running without using the CPU core 4  
Note: By default, 'top' does not show the load of individual cores, only shows the total load. For enabling it, once opened, simply press the '1' key. The amount of listed cores depend on your CPU.  

System monitor in Ubuntu showing that the CPU core 4 is under low stress
System monitor in Ubuntu showing that the CPU core 4 is under low stress
So anyway, as an ending note, if you are willing to sacrifice the performance a bit, but would like to run multithreaded software tools and carry out your other usual computer oriented tasks in Ubuntu without loosing the OS's responsiveness (somewhat), then this is one way of doing that.

Though the article might make it look complicated, once you get a hold of it, it is a two step based, extremely simple process. Good luck.

About the Author: Gayan is computer geek who has been using various GNU/Linux distributions for the past 10 years. He runs a blog called 'HecticGeek.com', where he writes primarily about open-source desktop applications and simple tips & tricks for Ubuntu Linux users (including occasional Windows applications).

4 comments:

  1. Excellent. Thanks for this useful tip

    ReplyDelete
  2. Is it possible to limit not just the number of cores, but also the time each core can dedicate to a specific process/thread?

    E.g.: I would like to let a process use at most 10% of the CPU time. This process could be... Shockwave Flash!

    ReplyDelete
    Replies
    1. Hello 'Pietro',

      First of all, sorry about the late response. I did not know there were any comments, until now :).

      Anyhow, concerning your question, yes it is possible to do that. There could be many tools available, and one is called 'cpulimit'.

      However, please remember that, though 'cpulimit' can limit the CPU time of an app, once you exit that app/process, the saved setting will be lost.

      Meaning that, every time you open that app/process, you will have to re-apply the cpu-time setting, manually.

      If you want simple explanation on how to use it, then please follow the below link.

      http://www.hecticgeek.com/2012/01/cpu-usage-limiter-ubuntu-linux/

      Note: I hope that you would forgive me if the English in that article seems crappy :).

      Delete