Martin Drozdik
Martin Drozdik

Reputation: 13303

Why is the CPU time different with every execution of this program?

I have a hard time understanding processor time. The result of this program:

#include <iostream>
#include <chrono>

// the function f() does some time-consuming work
void f()
{
    volatile long double d;
    int size = 10000;
    for(int n=0; n<size; ++n)
       for(int m=0; m<size; ++m)
           d = n*m;
}

int main()
{
    std::clock_t start = std::clock();
    f();
    std::clock_t end = std::clock();

    std::cout << "CPU time used: "
              << (end - start)
              << "\n";
}

Seems to randomly fluctuate between 210 000, 220 000 and 230 000. At first I was amazed, why these discrete values. Then I found out that std::clock() returns only approximate processor time. So probably the value returned by std::clock() is rounded to a multiple of 10 000. This would also explain why the maximum difference between the CPU times is 20 000 (10 000 == rounding error by the first call to std::clock() and 10 000 by the second).

But if I change to int size = 40000; in the body of f(), I get fluctuations in the ranges of 3 400 000 to 3 500 000 which cannot be explained by rounding.

From what I read about the clock rate, on Wikipedia:

The CPU requires a fixed number of clock ticks (or clock cycles) to execute each instruction. The faster the clock, the more instructions the CPU can execute per second.

That is, if the program is deterministic (which I hope mine is), the CPU time needed to finish should be:

  1. Always the same
  2. Slightly higher than the number of instructions carried out

My experiments show neither, since my program needs to carry out at least 3 * size * size instructions. Could you please explain what I am doing wrong?

Upvotes: 1

Views: 5123

Answers (4)

Ben
Ben

Reputation: 35613

Your program is not deterministic, because it uses library and system functions which are not deterministic.

As a particular example, when you allocate memory this is virtual memory, which must be mapped to physical memory. Although this is a system call, running kernel code, it takes place on your thread and will count against your clock time. How long it takes to do this will depend on what the overall memory allocation situation is.

Upvotes: 2

Mats Petersson
Mats Petersson

Reputation: 129364

The CPU time is indeed "fixed" for a given set of circumstances. However, in a modern computer, there are other things happening in the system, which interferes with the execution of your code. It may be that caches are being wiped out when your email software wakes up to check if there is any new emails for you, or when the HP printer software checks for updates, or when the antivirus software decides to run for a little bit checking if your memory contains any viruses, etc, etc, etc, etc.

Part of this is also caused by the problem that CPU time accounting in any system is not 100% accurate - it works on "clock-ticks" and similar things, so the time used by for example an interrupt to service a network packet coming in, or the hard disk servicing interrupt, or the timer interrupt to say "another millisecond ticked by" these all account into "the currently running process". Assuming this is Windows, there is a further "feature", and that is that for historical and other reasons, std::clock() simply returns the time now, not actually the time used by your process. So for exampple:

t = clock();
cin >> x;
t = clock() - t;

would leave t with a time of 10 seconds if it took ten seconds to input the value of x, even though 9.999 of those ten seconds were spent in the idle process, not your program.

Upvotes: 1

James Kanze
James Kanze

Reputation: 153909

First, the statement you quote from Wikipedia is simply false. It might have been true 20 years ago (but not always, even then), but it is totally false today. There are many things which can affect your timings:

  • The first: if you're running on Windows, clock is broken, and totally unreliable. It returns the difference in elapsed time, not CPU time. And elapsed time depends on all sorts of other things the processor might be doing.

  • Beyond that: things like cache misses have a very significant impact on time. And whether a particular piece of data is in the cache or not can depend on whether your program was interrupted between the last access and this one.

In general, anything less than 10% can easily be due to the caching issues. And I've seen differences of a factor of 10 under Windows, depending on whether there was a build running or not.

Upvotes: 8

softwarebear
softwarebear

Reputation: 451

You don't state what hardware you're running the binary on.

Does it have an interrupt driven CPU ?

Is it a multitasking operating system ?

You're mistaking the cycle time of the CPU (the CPU clock as Wikipedia refers to) with the time it takes to execute a particular piece of code from start to end and all the other stuff the poor CPU has to do at the same time.

Also ... is all your executing code in level 1 cache, or is some in level 2 or in main memory, or on disk ... what about the next time you run it ?

Upvotes: 3

Related Questions