Jak mogę zmierzyć czas procesora i czas zegara ściennego w Linuksie / Windows?

Mam na myśli: Jak mogę zmierzyć czas, jaki mój procesor spędził na wykonywaniu funkcji i czas potrzebny do uruchomienia mojej funkcji? (Jestem zainteresowany Linuksem / Windows i zarówno x86, jak i x86_64). Zobacz, co chcę zrobić (używam C++ tutaj, ale wolałbym C rozwiązanie):

int startcputime, endcputime, wcts, wcte;

startcputime = cputime();
function(args);
endcputime = cputime();

std::cout << "it took " << endcputime - startcputime << " s of CPU to execute this\n";

wcts = wallclocktime();
function(args);
wcte = wallclocktime();

std::cout << "it took " << wcte - wcts << " s of real time to execute this\n";

Kolejne ważne pytanie: czy ten rodzaj architektury pomiaru czasu jest niezależny czy nie?

Author: yak, 2013-07-02

4 answers

Oto rozwiązanie do kopiowania i wklejania, które działa zarówno na Windows i Linux, jak i C i C++.

Jak wspomniano w komentarzach, istnieje Biblioteka boost, która to robi. Ale jeśli nie możesz użyć Boosta, to powinno działać:

//  Windows
#ifdef _WIN32
#include <Windows.h>
double get_wall_time(){
    LARGE_INTEGER time,freq;
    if (!QueryPerformanceFrequency(&freq)){
        //  Handle error
        return 0;
    }
    if (!QueryPerformanceCounter(&time)){
        //  Handle error
        return 0;
    }
    return (double)time.QuadPart / freq.QuadPart;
}
double get_cpu_time(){
    FILETIME a,b,c,d;
    if (GetProcessTimes(GetCurrentProcess(),&a,&b,&c,&d) != 0){
        //  Returns total user time.
        //  Can be tweaked to include kernel times as well.
        return
            (double)(d.dwLowDateTime |
            ((unsigned long long)d.dwHighDateTime << 32)) * 0.0000001;
    }else{
        //  Handle error
        return 0;
    }
}

//  Posix/Linux
#else
#include <time.h>
#include <sys/time.h>
double get_wall_time(){
    struct timeval time;
    if (gettimeofday(&time,NULL)){
        //  Handle error
        return 0;
    }
    return (double)time.tv_sec + (double)time.tv_usec * .000001;
}
double get_cpu_time(){
    return (double)clock() / CLOCKS_PER_SEC;
}
#endif
Jest kilka sposobów na zaimplementowanie tych zegarów. Ale oto czego używa powyższy fragment:

Dla Windows:

Dla Linux:


A oto mała demonstracja:

#include <math.h>
#include <iostream>
using namespace std;

int main(){

    //  Start Timers
    double wall0 = get_wall_time();
    double cpu0  = get_cpu_time();

    //  Perform some computation.
    double sum = 0;
#pragma omp parallel for reduction(+ : sum)
    for (long long i = 1; i < 10000000000; i++){
        sum += log((double)i);
    }

    //  Stop timers
    double wall1 = get_wall_time();
    double cpu1  = get_cpu_time();

    cout << "Wall Time = " << wall1 - wall0 << endl;
    cout << "CPU Time  = " << cpu1  - cpu0  << endl;

    //  Prevent Code Elimination
    cout << endl;
    cout << "Sum = " << sum << endl;

}

Wyjście (12 wątków):

Wall Time = 15.7586
CPU Time  = 178.719

Sum = 2.20259e+011
 61
Author: Mysticial,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-10 00:01:32

C++11. Dużo łatwiej pisać!

Użyj std::chrono::system_clock do zegara ściennego i std::clock do zegara cpu http://en.cppreference.com/w/cpp/chrono/system_clock

#include <cstdio>
#include <ctime>
#include <chrono>

.... 

std::clock_t startcputime = std::clock();
do_some_fancy_stuff();
double cpu_duration = (std::clock() - startcputime) / (double)CLOCKS_PER_SEC;
std::cout << "Finished in " << cpu_duration << " seconds [CPU Clock] " << std::endl;


auto wcts = std::chrono::system_clock::now();
do_some_fancy_stuff();
std::chrono::duration<double> wctduration = (std::chrono::system_clock::now() - wcts);
std::cout << "Finished in " << wctduration.count() << " seconds [Wall Clock]" << std::endl;

Et voilà, łatwy i przenośny! Nie potrzeba # ifdef _win32 ani Linuksa!

Możesz nawet użyć chrono::high_resolution_clock, jeśli potrzebujesz większej precyzji http://en.cppreference.com/w/cpp/chrono/high_resolution_clock
 27
Author: carlduke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-28 22:38:12

Aby podać konkretny przykład sugestii @ Lipa, aby użyć boost::timer jeśli możesz (testowane Z Boost 1.51):

#include <boost/timer/timer.hpp>

// this is wallclock AND cpu time
boost::timer::cpu_timer timer;

... run some computation ...

boost::timer::cpu_times elapsed = timer.elapsed();
std::cout << " CPU TIME: " << (elapsed.user + elapsed.system) / 1e9 << " seconds"
          << " WALLCLOCK TIME: " << elapsed.wall / 1e9 << " seconds"
          << std::endl;
 12
Author: Andre Holzner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-13 08:46:36

Użyj metody clock w czasie .h :

clock_t start = clock();
/* Do stuffs */
clock_t end = clock();
float seconds = (float)(end - start) / CLOCKS_PER_SEC;

Niestety ta metoda zwraca czas procesora w Linuksie, ale zwraca czas Ścienny w Windows (dzięki komentarzom za te informacje).

 -1
Author: syb0rg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-02 18:18:43