On 04/25/2012 02:22 PM, (e-mail address removed) wrote:
Hi, can someone help with how I can throttle CPU usage in a c
application.
By means of an example, in this trivial application
int main(int argc, char *argv[]) {
int i;
while (1) {
i++;
}
}
how can I limit the CPU usage for the loop to be 10% or 20% or 50% or
whatever integer I pass in on the command line.
The C standard provides no mechanism for doing this; whether there is
any such mechanism, and how to use it, will depend upon your operating
system.
For instance, on unix-like systems:
sleep() provides a mechanism for relinquishing control of the CPU for a
period of time; To achieve a desired percentage of the time, use calls
to clock() to determine when the next time should be for a call to sleep().
If all you really want is to reduce your CPU usage, without needing
precise control over reduction, call the nice() function to lower the
scheduling priority for your process.
I was thinking of doing something like your suggestion but my
application will hopefully run on both Windows and Linux so I won't be
able to set process priority or the nice factor.
Where I got my idea from is from boinc. In boinc you can set the CPU
usage to be anything from 1-100, and even configure the program to
suspend itself when the computer is doing something else, so that is
using idle time and not being antisocial to whatever else the computer
is doing. I am thinking of something like this. Maybe as you suggest,
I will just check the time every now and then and for 20% usage, I
will just run at 100% CPU for short bursts, work out how much time it
took to do the burst, and then do nothing for 8 * that time, and
repeat.
The tricky part of that is "do nothing". The C standard doesn't provide
any mechanism for doing that; you'll have to find a method specific to
your operating system for doing it. That's what sleep() is for;
presumably there's a Windows equivalent - it might even be called
sleep(), for all I know.
In your example:
int i;
while(1) {
i++;
}
This code has undefined behavior for two separate reasons. First of all,
'i' is uninitialized; that means that it could, among other
possibilities, have a trap representation. Any attempt to read the value
of an object containing a trap representation has undefined behavior. On
a system where 'int' has no trap representations, which is most
real-world systems, that's probably not a problem, but you should get in
the habit of always initializing every variable sometime before the
first time that its value is read.
The second reason is that your program keeps incrementing 'i' until it
reaches INT_MAX, and then executes i++ one more time. As soon as it does
that, the behavior is undefined. In fact, as soon as it becomes
inevitable that this will happen (which is the moment your program
starts) the behavior is undefined. Again, on many systems this will do
something innocuous, such as set i to INT_MIN, but there's no guarantees
that the result will be that painless. You can avoid both problems by using
unsigned u = 0;
while(1) {
u++;
}
The behavior of u++ when u is UINT_MAX is well-defined; it sets u to 0.
Because your code makes no use of the value of i after the end of the
loop, a good optimizing compiler can convert your code into the
equivalent of:
int main(void) { while(1); }
It's been argued that a really good optimizing compiler can execute an
infinite empty loop in a finite amount of time, since infinity*0 has no
well defined meaning. The mathematical part of that argument is suspect,
but the C standard never specifies anything about how long your program
should take to execute, so it is arguably the case that such a compiler
could implement your program as the equivalent of
int main(void) { }
That's pretty much just a joke, but the underlying truth behind that
joke is that with modern optimizing compilers, the only way to make sure
that your loop actually wastes time doing something, is to make sure
that the thing it does can't be optimized away.
Getting back to my main point: if the thing your loop is doing can't be
optimized away, then it doesn't qualify as "do nothing".