5

I am currently writing an application in Windows using C++ and I would like to simulate CPU load.

I have the following code:

void task1(void *param) { 

unsigned elapsed =0;
unsigned t0;

while(1){

    if ((t0=clock())>=50+elapsed){//if time elapsed is 50ms

        elapsed=t0;
        Sleep(50);
    }
  }
}

int main(){

int ThreadNr;

for(int i=0; i < 4;i++){//for each core (i.e. 4 cores)
    _beginthread( task1, 0, &ThreadNr );//create a new thread and run the "task1" function
}

while(1){}
}

I wrote this code using the same methodology as in the answers given in this thread: Simulate steady CPU load and spikes

My questions are:

  1. Have I translated the C# code from the other post correctly over to C++?
  2. Will this code generate an average CPU load of 50% on a quad-core processor?
  3. How can I, within reasonable accuracy, find out the load percentage of the CPU? (is task manager my only option?)

EDIT: The reason I ask this question is that I want to eventually be able to generate CPU loads of 10,20,30,...,90% within a reasonable tolerance. This code seems to work well for to generate loads 70%< but seems to be very inaccurate at any load below 70% (as measured by the task manager CPU load readings).

Would anyone have any ideas as to how I could generate said loads but still be able to use my program on different computers (i.e. with different CPUs)?

Community
  • 1
  • 1
user206631
  • 77
  • 1
  • 2
  • 6

3 Answers3

8

At first sight, this looks like not-pretty-but-correct C++ or C (an easy way to be sure is to compile it). Includes are missing (<windows.h>, <process.h>, and <time.h>) but otherwise it compiles fine.

Note that clock and Sleep are not terribly accurate, and Sleep is not terribly reliable either. On the average, the thread function should kind of work as intended, though (give or take a few percent of variation).

However, regarding question 2) you should replace the last while(1){} with something that blocks rather than spins (e.g. WaitForSingleObject or Sleep if you will). otherwise the entire program will not have 50% load on a quadcore. You will have 100% load on one core due to the main thread, plus the 4x 50% from your four workers. This will obviously sum up to more than 50% per core (and will cause threads to bounce from one core to the other, resulting in nasty side effects).

Using Task Manager or a similar utility to verify whether you get the load you want is a good option (and since it's the easiest solution, it's also the best one).

Also do note that simulating load in such a way will probably kind of work, but is not 100% reliable.
There might be effects (memory, execution units) that are hard to predict. Assume for example that you're using 100% of the CPU's integer execution units with this loop (reasonable assumption) but zero of it's floating point or SSE units. Modern CPUs may share resources between real or logical cores, and you might not be able to predict exactly what effects you get. Or, another thread may be memory bound or having significant page faults, so taking away CPU time won't affect it nearly as much as you think (might in fact give it enough time to make prefetching work better). Or, it might block on AGP transfers. Or, something else you can't tell.

EDIT:

Improved version, shorter code that fixes a few issues and also works as intended:

  • Uses clock_t for the value returned by clock (which is technically "more correct" than using a not specially typedef'd integer. Incidentially, that's probably the very reason why the original code does not work as intended, since clock_t is a signed integer under Win32. The condition in if() always evaluates true, so the workers sleep almost all the time, consuming no CPU.
  • Less code, less complicated math when spinning. Computes a wakeup time 50 ticks in the future and spins until that time is reached.
  • Uses getchar to block the program at the end. This does not burn CPU time, and it allows you to end the program by pressing Enter. Threads are not properly ended as one would normally do, but in this simple case it's probably OK to just let the OS terminate them as the process exits.
  • Like the original code, this assumes that clock and Sleep use the same ticks. That is admittedly a bold assumption, but it holds true under Win32 which you used in the original code (both "ticks" are milliseconds). C++ doesn't have anything like Sleep (without boost::thread, or C++11 std::thread), so if non-Windows portability is intended, you'd have to rethink anyway.
  • Like the original code, it relies on functions (clock and Sleep) which are unprecise and unreliable. Sleep(50) equals Sleep(63) on my system without using timeBeginPeriod. Nevertheless, the program works "almost perfectly", resulting in a 50% +/- 0.5% load on my machine.
  • Like the original code, this does not take thread priorities into account. A process that has a higher than normal priority class will be entirely unimpressed by this throttling code, because that is how the Windows scheduler works.

    #include <windows.h>
    #include <process.h>
    #include <time.h>
    #include <stdio.h>
    
    
    void task1(void *)
    {
        while(1)
        {
            clock_t wakeup = clock() + 50;
            while(clock() < wakeup) {}
            Sleep(50);
        }
    }
    
    int main(int, char**)
    {
        int ThreadNr;
        for(int i=0; i < 4; i++) _beginthread( task1, 0, &ThreadNr );
    
        (void) getchar();
        return 0;
    }
    
Damon
  • 67,688
  • 20
  • 135
  • 185
  • Thank you for the reply. Sorry if this may be a basic question but, you said to replace the "last while(1){} with something that blocks rather than spins" such as Sleep. I'm sorry but how would I implement that in my code, while still continuing to run the CPU at 50% load? – user206631 Jan 09 '13 at 11:29
  • `while(1){}` is an endless loop that consumes 100% CPU on one core. You have 4 workers that produce a more-or-less 50% CPU load (which is what you want). Therefore, you do _not_ want to burn another 100% on one core for nothing, this will give more than the 50% you want. `Sleep(INFINITE)` does the same but consumes 0% CPU. A preferrable way, however, would be to have some kind of exit condition, otherwise your program will run forever until you kill it in TaskManager or reboot. So, either sleep for something other than "forever" or use a wait function. Or, wait for a keypress, or whatever. – Damon Jan 09 '13 at 11:53
  • I think I'm missing something here. From my understanding, when I run my code and have say Sleep(INFINITE) instead of the while(1){} shouldn't the task manager indicate CPU usage of 50%? – user206631 Jan 10 '13 at 04:11
  • Yes exactly. But with the `while`, it would be rather around 75%, and there would probably be heavy thread migration from one core to the other, as you have 5 competitors with equal priority for only 4 cores, and no matter how cleverly the OS schedules, it is not possible to deliver 150% CPU time on a core. Thus necessarily whenever a waiter wakes (this boosts its priority temporarily) it will kick the main thread to the wait queue (likely getting a different core later). Same is true for any other thread in another program. With that in mind, using a completion port would be a funny idea... – Damon Jan 10 '13 at 14:02
  • Completion ports, as you know, will wake up to _N_ blocked threads (default = number of CPU cores) at a time, waking another thread as one blocks, and blocking threads attempting to detach a message if there are already enough running. As a crazy idea, one should in theory be able to exploit this to much more closely model something like a simulated X%, without ever (only ever possibly for a fraction of a second) having the problem of having _N+1_ threads ready. But that's just a thought, might as well be that this doesn't work any better. – Damon Jan 10 '13 at 14:09
  • forgive me for my stupidity but, when I run that exact code with Sleep(INFINITE) instead of while(1){}, according to task manager my CPU usage is ~2-3%, if I try simulate with 60ms work, task manager indicates CPU usage at only ~25%. Is there a reason for this? – user206631 Jan 11 '13 at 08:54
  • @user206631: The reason can be seen from looking at what the worker threads are doing. They're spending almost all their time (99.99%) inside `Sleep`, which suggests that the `if()` condition is evaluated wrong. Therefore they don't consume CPU time. I've corrected and simplified your code and verified if it works correctly (see edit above). – Damon Jan 11 '13 at 13:33
2

Here is an a code sample which loaded my CPU to 100% on Windows.

#include "windows.h"

DWORD WINAPI thread_function(void* data)
{
    float number = 1.5;
    while(true)
    {
        number*=number;
    }
    return 0;
}

void main()
{
    while (true)
    {
        CreateThread(NULL, 0, &thread_function, NULL, 0, NULL);
    }
}

When you build the app and run it, push Ctrl-C to kill the app.

1

You can use the Windows perf counter API to get the CPU load. Either for the entire system or for your process.

selbie
  • 100,020
  • 15
  • 103
  • 173