Question

I need to write a program that consumes a fixed fraction of the processor, I was thinking of changing the priority but this method doesn't restrict the CPU use to a fixed percentage for example 60%. Thanks!

Was it helpful?

Solution

Depends over what period you want this limit to be - if you want an absolute restriction to never use more than 60% (or less) then it can't reliably be done with your requirements (not using any other external commands or programs) - at the end of the day, the OS decides how much time you get.

However, if you just want it on average then you can potentially do it (with a couple of restrictions). Basically, set up a loop that notes the system time when it starts, performs a small amount of work, then notes the new system time. Now sleep the process for 2/3rds (for 60%) of the difference. You will need to maintain a buffer as there is no ensuring that you won't be slept for longer however. Also, if you are running a pre-emptable kernel, (which most are these days), then you are in trouble as the loop execution itself can get taken over.

tl;dr: You can approximately do it without outside code, but it is only going to be roughly right at best.

OTHER TIPS

There are many challenges you must deal to run a program consuming an almost-constant value of CPU (CPU time). Even if you use cpulimit you must consider at least three elements:

  • Which processes must be limited: The current Linux CFS scheduler tries to give the same time to all the processes that demand CPU and have the same priority. Then, if you have two CPU-bounded processes running in a computer with a single core, it will try to give them the same CPU time to both. When you use cpulimit you set an upper limit. Your process may use less. In order to set an almost-constant value all the time, you may need to limit the CPU not only of your process but also of all the others.
  • Which percentage you try to consume: The CPU percentage reported by top and other tools correspond to the percentage used on each core (or thread for hyperthreading CPUs). If you use use tools such as cpulimit to limit a process to use the 50%, you are limiting the process to the 50% of a core. If you have 8 cores, you must use the value of 400% to limit the CPU consumption to the half of the cores.
  • How many cores you try to exercise: Each thread in a process is assigned to a core when it runs. If you need to exercise more than a core, you need to start more processes or threads.

Using cpulimit

cpulimit sets an upper limit for the CPU consumption of one or more processes. It monitors the process and send signals to the process to suspend their execution if it starts to consume more than the limit. It resumes the process when the CPU consumption goes below the limit.

Consider that you run a CPU-bounded process such as md5sum /dev/zero &, you may use top to verify that the process uses the 100% of a CPU and use cpulimit to limit the CPU consumption. Note that the command returns the process id (pid) of the process. It is 77 in the example

$ md5sum /dev/zero &
[1] 77

To limit the CPU consumption, you may use cpulimit and the process id reported by the system. The following is an example. You can use -v to get verbose messages. Note that, even if you set 25% as the limit, the CPU consumed is not 25% all the time, sometimes it goes below (21.30%) and sometimes it goes further (36.87%)

$ sudo cpulimit --verbose --limit=25 --pid=77
4 CPUs detected.
Priority changed to -10
Process 77 detected

%CPU    work quantum    sleep quantum   active rate
26.99%   46144 us        53855 us       49.83%
21.30%   65714 us        34285 us       55.98%
28.47%   47762 us        52237 us       54.39%
36.45%   39202 us        60797 us       57.16%
36.87%   37513 us        62486 us       55.33%
   :

The process id (pid) can be used to send signals to the process too. For instance, you can use kill to send a SIGSTOP signal and suspend its execution. You can send a SIGCONT signal to resume the execution.

$ kill -s SIGSTOP 77       # suspend the execution of process 77 (it will use 0% CPU)
$ kill -s SIGCONT 77       # resume the execution of process 77

How cpulimit works

You can get the source code for cpulimit in Github.

$ git clone https://github.com/opsengine/cpulimit.git
$ cd cpulimit
$ make                              # compile the code
$ sudo cp src/cpulimit /usr/bin     # install the command 

Basically, cpulimit creates a process group whith all the process it controls. You may check the process_group.c file. It includes functions to create and update that linux process group. In addition, there are other functions to find a process by pid or by name and add them to the group. The update_process_group function is used to update constantly the CPU consumption of the processes in the group.

In the cpulimit.c, the limit_process does all the work. There is an while(1) { ... } infinite loop that checks the CPU consumed by each process. If the process is consuming more than the limit, it sends a SIGSTOP (suspend) signal. If the process is suspended and using less then the limit, it sends a SIGCONT (resume) signal.

An idea: how to implement your program

I have already seen the source code of "cpulimit" but I didn't find out how to make my c program waste exactly and always for example 60% of the processor!

To create a process that use the 50% of a CPU all the time, you must monitor the other processes running in the same core and limit the time consumed by all these processes. The sum of the CPU used by the other processes in the same core must not exceed 50%. You may define a CPU affinity to set which processes will run on the same core all the time.

$ taskset -p -c 0 77        # make that process 77 use the core 0 

You may find some shell scripts that take all the running processes that comply with some criteria and limit their CPU consumption by using cpulimit. The following is an example that limits all the processes that use more than 20% of the CPU.

#!/bin/bash

while sleep 3        # execute each 3 seconds
do 
   # get the processes that use more than 20% of CPU
   PIDS=`top -b -n1 | tail -n +8 | gawk '$9>20 {print $1}'`
   for i in $PIDS
   do
      # limit the new violating processes to 20%
      cpulimit -p $i -l 20 -z &    
   done
done

Another idea: Using cgroups (?)

As an alternative to cpulimit, you may explore the use of Process Control Groups (cgroups). These groups are different than the process groups used by the cpulimit. The cgroup is a feature of the Linux kernel that allows you to set limits to groups of processes. It can be used, for instance, to limit the CPU and network used by administrative processes and reduce the interference of these tasks to the servers running in the same machine.

You may check a solution that limits the CPU usage using cgroup.

Here is a thread that discusses several ways of obtaining CPU statistics: http://www.cyberciti.biz/tips/how-do-i-find-out-linux-cpu-utilization.html. At the very least, you can get CPU utilization programmatically by reading /sys/devices/xxx/cpuN.

There are ways to do what you want, but you haven’t given us enough detail as to your objective. If you want to impact energy consumption, you can simply max out one processor (less the load of your other applications). If you want to impact the execution of one application, you need to be more clever. If you want to place a general fixed load on your processor regardless of your application suite, it can get very complicated and we need to know more about your use case.

Outside of that, there are also some other things that you should be aware of when you try. The first is that you need to decide how grainy you want your utilization to be. Here’s what I mean. CPU utilization is evaluated over a window. It’s possible to have an average utilization of, say, 60% but if your utilization computation window is, say 2 seconds, you might be computing for .6*2 or 1.2sec and idle for .8sec. And .8sec is a long time on a modern processor. After figuring out what grain you want, then you can use the techniques that Oliver suggests. Another technique is to measure the current CPU utilization and then calculate the ratio of the number of milliseconds you need to sleep vs work. Then perform a simple loop and call your favorite sleep function. (A word of warning about computational loops. Modern compilers are danged good at optimizations and might reduce the length of time your computation loop requires significantly.) You also need to make sure this utilization is spread across all processors. I’m not going to get into complications that can arise due to hyper-threading.

When you determine your grain, note that timing resolutions on most Linux systems (or any others, for that matter) are >10msec no matter what the API allows.

Re: Maximizing the load on one CPU. I doubt this will work for you. If your app is single threaded, putting a load on another CPU is not going to impact the performance of your app. If your app is very heavily threaded, it will probably still not work because some OSs will attempt to even out the load across CPUs, meaning that it might still move your threads away from the more heavily loaded CPU, and once again not impact your app in the way you want.

In summary, we have to know more to have a chance of offering a solution.

PS I The code you used in your comment to Oliver doesn’t work because you are doing no processing.

I guess https://github.com/opsengine/cpulimit can do the job for you. It's opensource, so check out the sources too and fork it ftw!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top