How can I make a program run for a given amount of time on the CPU in C++?

61 Views Asked by At

"I want to write a program that consumes 5 seconds of CPU time, where the time spent off the CPU due to IO, context switches, etc., is not counted towards this 5-second time quota.

Currently, I've used the std::chrono approach, but it obviously doesn't meet the requirements, as when I call sleep to yield the CPU, this one second is also counted towards the program's execution time. Resulting in a low task-clock in perf.

#include <chrono>
#include <thread>
#include <iostream>
#include <cmath>

int main() {
    auto start = std::chrono::high_resolution_clock::now();
    auto end = start;

    while (true) {
        end = std::chrono::high_resolution_clock::now();

        auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(end - start);

        if (elapsed.count() >= 5) {
            break;
        }

        volatile double d = 0;
        for (int n = 0; n < 10000; ++n) {
            d += std::sqrt(n);
        }

        std::this_thread::sleep_for(std::chrono::seconds(1));
        std::cout << "wake" << std::endl;
    }

    std::cout << "CPU time used: 5 seconds" << std::endl;
    return 0;
}

In this test, it's possible to manually exclude the time spent in sleep by tracking it, but for involuntary CPU yields (such as CPU time-sharing that occurs when there are a large number of threads), it's not possible to account for this off-CPU time through code.

2

There are 2 best solutions below

2
sandip sonar On
#include<iostream>
#include<time.h>
#include<cmath>

using namespace std;
int main(){
clock_t start=clock();
volatile double d=0;

while((clock()-start)/CLOCKS_PER_SEC<5){
    for(int n=0;n<10000;++n){
        d+=sqrt(n);
    }
}
cout<<"CPU time used: 5 seconds"<<endl;
return 0;
}
0
Deepak D On

One interesting-yet-prone-to-errors option is to measure the CPU cycles a function takes from the TSC (Time Stamp Counter) register. And infer the "real cpu time" taken from it, provided we take care of the following:

  • The program is set to run on a single core (i.e., set the cpu affinity).
  • The function needs to rerun many times (in a loop) to account for the variance in the output of rdtsc, the function/opcode that returns CPU clock ticks.

This article goes in depth of this approach, and shows the examples of various math functions.

/*
    James William Fletcher (github.com/mrbid)
        August 2021

    Simple math function benchmark using RDTSC.
    https://james-william-fletcher.medium.com/rdtsc-the-only-way-to-benchmark-fc84562ef734
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include <locale.h>
#include <x86intrin.h>

#define AVGITER 3000000


int main()
{
    setlocale(LC_NUMERIC, "");
    float ret = 0;
    uint64_t st = 0, et = 0, avg = 0;

    avg = 0;
    for(int i = 0; i < AVGITER; i++)
    {
        st = __rdtsc();
        ret += log10(st);
        avg += __rdtsc()-st;
    }
    printf("log10() Cycles: %'lu\n", avg / AVGITER);
    return 0;
}
Output:
log10() Cycles: 68

Resources: