Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

QueryPerformanceCounter - a dokładność w zliczaniu czasu wykonywania algorytmu

Ostatnio zmodyfikowano 2015-11-23 22:08
Autor Wiadomość
ArgonZapan
Temat założony przez niniejszego użytkownika
QueryPerformanceCounter - a dokładność w zliczaniu czasu wykonywania algorytmu
» 2015-11-18 19:33:54
Witam
Mam za zadanie porównać czas wykonywania 2 algorytmów optymalnych dla komiwojażera. Dla 7 różnych reprezentacyjnych wartości N, czyli teoretycznie od 3, wzwyż, zrobić po 100 testów i uśrednić wyniki. 1 to przegląd zupełny, 2 to metoda podziału i ograniczeń. No i pojawia się problem bo jeden wykonuje się bardzo szybko a drugi bardzo powoli. Używając 2 algorytmu dla N < 11, jest to 0 lub 0.015s, jeśli używam funkcji clock(), a dla 1 algorytmu dla N > 12, trwa wieki.
Więc szukając po sieci napotkałem taką stronkę:
[url]http://timofiejew.ii.uph.edu.pl/Archiwum/Projekt_grupowy_2008_2009/Pomiar_czasu_wykonania_algorytmu.pdf[/url]
Na ostatniej stronie jest informacja że można zliczać czas za pomocą ilości taktowań, co jest na pozór dobrym rozwiązaniem mojego problemu bo mógłbym dokładnie wyliczyć czas dla małych N.
Ale później sobie przypomniałem o tym, że kiedyś gdzieś wyczytałem, że jak były jeszcze procesory 1 rdzeniowe, to można było robić wiele rzeczy na raz, dzięki temu że Windows zarządza procesorem i przydziela po kawałku moc obliczeniową dla każdej czynności i mamy wrażenie że dzieje się kilka rzeczy jednocześnie. A teraz żyjemy w świecie gdzie nie ma 1 rdzenia i tu jest sedno mojego pytania.
Czy odpalając testy, Windows nie wrzuci mi jakichś innych programów działających w tle, do różnicy QueryPerformanceCounter ?
Oraz, jak jest zliczane dokładnie? No bo program jest jedno wątkowy, a nie widzę w tym kodzie nic o tym aby zliczać dla jakiegoś jednego rdzenia czy coś w tym rodzaju ?
A może za każdym przerwaniem program ląduje w innym rdzeniu i nic nie da mi zliczanie ilości taktów ?

Albo może ktoś zna inny dokładniejszy sposób zliczania czasu niż clock();
P-140343
j23
» 2015-11-18 20:12:09
QueryPerformanceCounter jest OK do tego typu pomiarów. Możesz spróbować std::chrono::high_resolution_clock jeśli piszesz w C++. Co do zafałszowywania wyników przez inne procesy. Tego nie da się uniknąć w 100%, dlatego mierzy się czas np. 100, 1000 lub 10000 wykonań i liczy średnią.


PS. jeśli dobrze pamiętam, clock miał skok co 5-10ms.
P-140349
ArgonZapan
Temat założony przez niniejszego użytkownika
» 2015-11-18 20:16:30
Dzięki za rozwianie moich obaw, u mnie akurat ma skok co ~15ms :) Na forum znalazłem przedtem wątek że co 1/400s = 2.5ms ale jakoś u mnie to inaczej wygląda.
P-140351
DejaVu
» 2015-11-19 22:43:52
Za pomocą funkcji o którą się pytasz możesz mierzyć z dokładnością większą niż jedna nanosekunda.
https://msdn.microsoft.com​/en-us/library/windows/desktop​/ms644904(v=vs.85).aspx
P-140409
ArgonZapan
Temat założony przez niniejszego użytkownika
» 2015-11-23 22:08:11
Dla potomnych, bo nie ma jeszcze żadnego wątku o tym na forum.
część kodu zaczerpnięta z http://stackoverflow.com​/questions/1739259​/how-to-use-queryperformancecounter

C/C++
double PCFreq = 0.0;
__int64 CounterStart = 0;

void StartCounter()
{
    LARGE_INTEGER li;
    if( !QueryPerformanceFrequency( & li ) )
         cout << "QueryPerformanceFrequency failed!\n";
   
    PCFreq = double( li.QuadPart ) / 1000.0;
   
    QueryPerformanceCounter( & li );
    CounterStart = li.QuadPart;
}
double GetCounter()
{
    LARGE_INTEGER li;
    QueryPerformanceCounter( & li );
    return double( li.QuadPart - CounterStart ) / PCFreq;
}

void Test() {
    double TimeBruteForce[ 7 ] = { 0 };
    double TimeBranchAndBound[ 7 ] = { 0 };
   
   
    for( int j = 4, k = 0; j < 11; j++, k++ ) {
        for( int i = 0; i < 100; i++ ) {
            generateSample( j );
            StartCounter();
            BruteForce( track, 0 );
            TimeBruteForce[ k ] += GetCounter();
            StartCounter();
            BranchAndBound( matrixOfCost, matrixOfCostSize, INT_MAX );
            TimeBranchAndBound[ k ] += GetCounter();
            system( "cls" );
            cout << "Test zakonczony dla " << j << " miast " << i << "%" << endl;
        }
    }
    for( int i = 0; i < 7; i++ ) {
        TimeBruteForce[ i ] /= 100;
        TimeBranchAndBound[ i ] /= 100;
        cout << "Sredni czas dla " << i + 4 << " miast " << endl;
        cout << "BruteForce: " << TimeBruteForce[ i ] << endl;
        cout << "BranchAndBound: " << TimeBranchAndBound[ i ] << endl;
        cout << endl;
    }
}

oraz jak dokładne są wyniki:

Sredni czas dla 4 miast
BruteForce: 0.0121476 ms
BranchAndBound: 0.0057103 ms

Sredni czas dla 5 miast
BruteForce: 0.0617757 ms
BranchAndBound: 0.0110827 ms

Sredni czas dla 6 miast
BruteForce: 0.360695 ms
BranchAndBound: 0.0334427 ms

Sredni czas dla 7 miast
BruteForce: 2.57075 ms
BranchAndBound: 0.0674929 ms

Sredni czas dla 8 miast
BruteForce: 21.1152 ms
BranchAndBound: 0.240092 ms

Sredni czas dla 9 miast
BruteForce: 190.125 ms
BranchAndBound: 0.592145 ms

Sredni czas dla 10 miast
BruteForce: 1971.94 ms
BranchAndBound: 2.09309 ms

To było to czego potrzebowałem, clock() jest zbyt mało dokładny.
P-140672
« 1 »
  Strona 1 z 1