Why is CLOCKS_PER_SEC not the actual number of clocks per second?
Asked Answered
L

6

37

I have just written this short C++ program to approximate the actual number of clock ticks per second.

#include <iostream>
#include <time.h>

using namespace std;

int main () {

    for(int i = 0; i < 10 ; i++) {

        int first_clock = clock();
        int first_time = time(NULL);

        while(time(NULL) <= first_time) {}

        int second_time = time(NULL);
        int second_clock = clock();

        cout << "Actual clocks per second = " << (second_clock - first_clock)/(second_time - first_time) << "\n";

        cout << "CLOCKS_PER_SEC = " << CLOCKS_PER_SEC << "\n";

    }

    return 0;

}

When I run the program, I get output that looks like this.

Actual clocks per second = 199139
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 638164
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 610735
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 614835
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 642327
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 562068
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 605767
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 619543
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 650243
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 639128
CLOCKS_PER_SEC = 1000000

Why doesn't the actual number of clock ticks per second match up with CLOCKS_PER_SEC? They're not even approximately equal. What's going on here?

Liddle answered 4/5, 2012 at 20:43 Comment(3)
Note that you might loop for less than a second. If you call time, and there are 200ms left for the next second, then you'll loop ~200ms. This is probably not the main problem here, anyway.Incumbency
Right, I realize that that's the reason why the first iteration of the loop returns a smaller result than the subsequent iterations. But my question is about the subsequent iterations. I guess I should have made that clear.Liddle
Now you still get the overhead of your cout in each subsequent iteration. Wait until you're at the start of a second before you start your measurement.Monocyclic
R
37

clock returns the amount of time spent in your program. There are 1,000,000 clock ticks per second total*. It appears that your program consumed 60% of them.

Something else used the other 40%.

*Okay, there are virtually 1,000,000 clock ticks per second. The actual number is normalized so your program perceives 1,000,000 ticks.

Readjust answered 4/5, 2012 at 20:54 Comment(0)
R
21

From the man page of clock(3):

POSIX requires that CLOCKS_PER_SEC equals 1000000 independent of the actual resolution.

Your implementation seems to follow POSIX at least in that respect.

Running your program here, I get

Actual clocks per second = 980000
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 1000000
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 990000
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 1000000
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 1000000
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 1000000
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 1000000
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 1000000
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 1000000
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 1000000
CLOCKS_PER_SEC = 1000000

or similar output on an idle machine, and output like

Actual clocks per second = 50000
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 600000
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 530000
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 580000
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 730000
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 730000
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 600000
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 560000
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 600000
CLOCKS_PER_SEC = 1000000
Actual clocks per second = 620000
CLOCKS_PER_SEC = 1000000

on a busy machine. Since clock() measures the (approximate) time spent in your program, it seems that you tested on a busy machine, and your program got only about 60% of the CPU time.

Restaurant answered 4/5, 2012 at 20:47 Comment(1)
While this is technically true, since the system call he is using also respects that it's kind of useless.Luba
B
6
  1. CLOCKS_PER_SECOND in POSIX is a constant equal to 1000000.
  2. CLOCKS_PER_SECOND is not supposed to show the number of clock in your process. It is a resolution number that you may use to convert the number of clocks to amount of time.(See man page for clock() function)

For example if you calculate:

(second_clock-first_clock)/CLOCKS_PER_SEC

you will get total time between first and second call to "clock()" function.

Bainmarie answered 9/12, 2015 at 22:31 Comment(1)
* CLOCKS_PER_SEC. Don't feel bad - my glibc's time.h uses CLOCKS_PER_SECOND in a comment too.Tabber
P
1

C99 standard

The only thing the C99 N1256 standard draft says about CLOCKS_PER_SEC is that:

CLOCKS_PER_SEC which expands to an expression with type clock_t (described below) that is the number per second of the value returned by the clock function

As others mention, POSIX sets it to 1 million, which limits the precision of this to 1 microsecond. I think this is just a historical value from days where the maximum CPU frequencies were measured in Mega Hertz.

Philodendron answered 16/4, 2016 at 13:10 Comment(0)
V
0

When you set int first_time = time(NULL);, time(NULL) might be "1 nanosecond away", (because it is truncated), from turning +1. Therefore, the: while(time(NULL) <= first_time) {} can be jumped over faster than 1 second, quicker than you expected.

That's why there are less clocks in that "1 second" of yours.

Vogue answered 18/9, 2020 at 0:31 Comment(0)
E
-2

Well duh. You don't know how far into the current second you start the timing, do you? So you can get any result from 1 to CLOCKS_PER_SEC. Try this in your inner loop:

int first_time = time(NULL);
// Wait for timer to roll over before starting clock!
while(time(NULL) <= first_time) {}

int first_clock = clock();
first_time = time(NULL);
while(time(NULL) <= first_time) {}

int second_time = time(NULL);
int second_clock = clock();

cout << "Actual clocks per second = " << (second_clock - first_clock)/(second_time - first_time) << "\n";

cout << "CLOCKS_PER_SEC = " << CLOCKS_PER_SEC << "\n";

See ideone for full source code. It reports actual clocks per second as 1000000, as you would expect. (I had to reduce the number of iterations to 2, so that ideone didn't time out.)

Educational answered 4/5, 2012 at 21:4 Comment(5)
This only explains why the first result is wrong; it has no bearing on the other nine. (unless the I/O is taking a whole third of a second for some strange reason)Nicks
@Hurkyl: Whatever the reason, it's clear that the two cout statements are taking about a third of a second to execute. Try out my version, if you don't believe me.Educational
It's not clear -- it's just a possibility. The other major possibility is that the discrepancy is due to clock not measuring wall-clock time. The next most likely, IMO, is low resolution on clock and/or time.Nicks
@Hurkyl: Why don't you just try out my version? Then we'll have some data to discuss. The full source code is at the ideone link.Educational
I had already deleted an answer that contained that very same fix before you posted your answer. I deleted it for basically the reason I gave in my comments above. Note that Rob had already posted one of the 'gotcha's of the clock function, and Daniel had demonstrated its relevance.Nicks

© 2022 - 2024 — McMap. All rights reserved.