6

What's the relationship between the real CPU frequency and the clock_t (the unit is clock tick) in C?

Let's say I have the below piece of C code which measures the time that CPU consumed for running a for loop.
But since the CLOCKS_PER_SEC is a constant value (basically 1000,000) in the C standard library, I wonder how the clock function does measure the real CPU cycles that are consumed by the program while it runs on different computers with different CPU frequencies (for my laptop, it is 2.6GHz).

And if they are not relevant, how does the CPU timer work in the mentioned scenario?

#include <time.h>
#include <stdio.h>
int main(void) {
  clock_t start_time = clock();    
  for(int i = 0; i < 10000; i++) {}
  clock_t end_time = clock();
  printf("%fs\n", (double)(end_time - start_time) / CLOCKS_PER_SEC); 
  return 0;
}
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Jason Yu
  • 1,886
  • 16
  • 26
  • 1
    It relates by the uhh, current ratio? Timing is provided by fixed sources, eg [oscillator circuits](https://en.wikipedia.org/wiki/Crystal_oscillator). As most modern CPUs have dynamic frequencies, it would be impossible to have reliable timing “based on” the CPU frequency. – user2864740 Jan 09 '22 at 07:56
  • 1
    What makes you think that measuring/knowing/using the CPU cycles is involved? For providing the elapsed time, it is only necessary to measrure the time. Reading a hardware timer would be one way to do so. Note that even if you would know the used CPU cycles, calculating the elapsed time from that info is near impossible nowadays, in the presence of pipelines, parallelisms, interrupts, branch prediction and whatnot. – Yunnosch Jan 09 '22 at 07:57
  • `CLOCKS_PER_SEC` simply gives the *unit of measurement* for the value returned by `clock()`. It isn't "basically 1000,000" but whatever the OS/compiler decide it should be. For example on my system it is 1000. That's one reason why it is a fairly blunt tool for timing purposes - it's granularity will vary from one system to another. – Weather Vane Jan 09 '22 at 09:04
  • I think we might be looking at a https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem Please consider whether you actually want to discuss how `clock()` works or whether you might indeed want to know how to measure the CPU ticks spent on the current program. Or maybe how to measure the time spent on the current program in a multithreading (possibly multi-CPU) environment. Those are different questions and you should ask the one you want answered, instead of getting lost on a detail which you think will give you the answer. – Yunnosch Jan 09 '22 at 09:22
  • However, if you actually want a different question answered than asked here, please keep this one as it is (with its upvoted answers) and create a separate new question post. Instead of fundamentally changing this one, thereby invalidating the answers. – Yunnosch Jan 09 '22 at 09:23
  • @Yunnosch I opened another question: https://stackoverflow.com/questions/70639995/how-does-the-clock-function-work-behind-the-scene-in-a-multithreading-program?noredirect=1#comment124875121_70639995 – Jason Yu Jan 09 '22 at 09:38

3 Answers3

7

Effectively, clock_t values are unrelated to the CPU frequency.

See longer explanation here.

While clock_t-type values could have, in theory, represented actual physical CPU clock ticks - in practice, they do not: POSIX mandates that CLOCKS_PER_SEC be equal to 1,000,000 - one million. Thus the clock_t function returns a value in microseconds.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • It's necessary for it to be some fixed constant for binaries compiled on one system to work on another. Even back in the days of fixed CPU frequency, different systems of the same architecture could have different core clock frequencies. And anyway, it's a software clock, incremented by timer interrupts or accounted on context switches, not derived directly from core clock cycles in normal implementations. – Peter Cordes Aug 19 '22 at 19:39
3

There is no such thing as "the real CPU frequency". Not in everyone's laptop, at any rate.

On many systems, the OS can lower and raise the CPU clock speed as it sees fit. On some systems there is more than one kind of central processor or core, each with a different speed. Some CPUs are clockless (asynchronous).

Because of all this and for other reasons, most computers measure time with a separate clock device, independent from the CPU clock (if any).

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
1

For providing the information used in the shown code, measuring/knowing/using the CPU cycles is not relevant.

For providing the elapsed time, it is only necessary to measure the time.
Reading a hardware timer would be one way to do so.
Most computers (even non-embedded ones) do contain timers which are especially counting ticks of a clock with known constant frequency. (They are specifically not "CPU timers".)
Such a timer can be read and yields a value which increases once per tick (of constant period). Where "known period" means a period know to some appropriate driver for that timer, simplified "known to the clock() function, not necessarily known to you".

Note that even if the number of used CPU cycles were known, calculating the elapsed time from that info is near impossible nowadays, in the presence of:

  • pipelines
  • parallelisms
  • interrupts
  • branch prediction

More things influencing/preventing the calculation, from comment contribution:

frequency-scaling, temperature throttling and power settings (David C. Rankin)

Yunnosch
  • 26,130
  • 9
  • 42
  • 54
  • :-) I assume you do not mind me using that for extending the list. Thanks. @DavidC.Rankin – Yunnosch Jan 09 '22 at 08:12
  • @DavidC.Rankin Interesting that you also leave out "cache". I did so intentionally, reasoning that while they can and usually do influence the number of CPU cycles and the resulting duration/time, they do not influence the ratio cycles/time. I guess you thought similarily. – Yunnosch Jan 09 '22 at 08:21
  • Aside ... I just went and checked and I have an old i7-2620M that bounces between 760MHz and 3.2GHz moment by moment. The CPU freq. would provide no useful info at all. – David C. Rankin Jan 09 '22 at 08:22
  • So, how does the CPU timer work in the mentioned scenario? – Jason Yu Jan 09 '22 at 08:43
  • @JasonYu I added some lines on that. – Yunnosch Jan 09 '22 at 08:52
  • So, you mean the timer is not part of the CPU? But in this case, how does the clock know when the CPU is scheduled to run the current program? Since the clock function only records the time consumption of each individual CPU that executes the current program. Meaning in a multi-threaded program, the returned value would be higher than the wall-clock time. – Jason Yu Jan 09 '22 at 09:12
  • "how does the clock know when the CPU is scheduled to run the current program?" I think it does not - and that it is a feature. "in a multi-threaded program, the returned value would be higher than the wall-clock time" Your understanding and mine are different here. If clock only would measure time while the CPU is processing the given program, then the measured time would be shorter than wall clock, not longer. Even if my understanding is wrong. Your phrasing of your understanding seems inconsistent to me. – Yunnosch Jan 09 '22 at 09:17
  • @Yunnosch You are right, it would be shorter. My mistake. – Jason Yu Jan 09 '22 at 09:25
  • I stay with basically "wall clock time". You do not have to trust me. But you should probably clarify what you want to discuss, see my comment on the question. Then others can give an answer which is immediatly helpful to you. And they might contradict me and I learn something.... – Yunnosch Jan 09 '22 at 09:27
  • (Wide) pipelines, branch prediction, and instruction-level parallelism aren't problems for determining elapsed time from core clock cycles. If some code takes a million cycles, and you happen to know the clock was ticking at an average of 1GHz over that period, that's 1 millisecond. Regardless of how many of those cycles were wasted due to mispredicts, or got multiple instructions executed on a wide pipeline. Those would be concerns if you were trying to predict performance from a known sequence of instructions, but you're proposing that you already have a cycle count measurement. – Peter Cordes Aug 19 '22 at 19:48
  • The problems are variable CPU frequency, and if you want to not count interrupts (but do want to count kernel time in system calls). I suspect that most systems *do* count interrupt-handler time against the current task, instead of spending extra time in short IRQ handlers doing accounting for time. The former problem can be avoided by using a fixed clock as a timesource, e.g. `rdtsc` on modern x86 systems which ticks at constant frequency regardless of actual CPU speed. But that reference frequency varies by CPU model. Modern Linux uses rdtsc for extra precision between timer int ticks. – Peter Cordes Aug 19 '22 at 19:51