Czas wykonywania kodu po kompilacji debug a release

0

Witam,

Piszę konsolowy programik mierzący czas wykonywania się kodu w asemblerze oraz w C++. Program składa się z czterech "etapów", których czasy wykonania są mierzone. Są to kolejno:

  1. Krótka pętla we wstawce asemblerowej
  2. Jej odpowiednik w C++
  3. Wywołanie programu .com (napisanego wcześniej w asemblerze - pomiar czasu jest wykonywany w tym podprogramie)
  4. Wywołanie funkcji która wykonuje to samo co program .com (wielokrotne obliczanie silni)

Wszystko było dobrze, gdy kompilowałem program w trybie debug - czasy pierwszych dwóch kroków wynosiły bodajże odpowiednio 0,016 oraz 0,045 sekund, etap 3 - około 50 sekund, etap 4 - około dwie minuty. Chciałbym jednak odpalić program na innym komputerze, żeby porównać wyniki - kompiluję w trybie release i okazuje się że czasy kroków 2 i 4 wynoszą jakieś śmieszne małe wartości - w obu przypadkach około jednej miliardowej sekundy - niezależnie od tego czy odpalam program u siebie czy na tym drugim komputerze.
Czasy wykonywania się kodu asemblerowego oraz programiku .com są (mniej więcej) takie same).

Dlaczego? Oczywiście zdaję sobie sprawę, że program powinien się wykonywać szybciej po kompilacji w trybie release, ale... żeby z dwóch minut zjechać do prawie zera??

Do pomiaru czasu używam funkcji QueryPerformanceCounter() (oprócz kroku 3 oczywiście). Używam VC++ 2005 Express.

Z góry dzięki za jakąkolwiek pomoc :)

0

tyle, żeby pomiar miał jakąś wartość to czas wykonywania pomiaru musi być dłuższy.
Dodaj do tego pętlę która spowoduje, że będziesz obliczał to samo np 1000 razy.
Czas wykonywania powtórzeń umożliwi ci obliczenie średniego czasu wykonywania.

Najprawdopodobniej czas wykonywania spadł ci poniżej zdolności rozdzielczej QueryPerformanceCounter() (a raczej na pewno).

0

Chyba nie wyraziłem się jasno.

Nie otrzymuję wyniku zero. Dokładny wynik, który drukuję na ekranie to 0.0000010 (nie jestem pewien dokładnej liczby zer, myślę że to nieistotne w tym momencie).

Pętla już jest. Obliczam to samo okoła miliarda razy (chyba 924 miliony jeżeli być ścisłym). Czas wykonywania tych obliczeń po skompilowaniu programu w trybie debug wyniósł prawie dwie minuty!

Liczenie średniej nie jest istotne - mi nie zależy teraz na tym , żeby wyniki były jak "najdokładniejsze" - interesuje mnie to, dlaczego są tak olbrzymie rozbieżności między wynikami generowanymi przez ten sam program kompilowany w trybie debug i release.

0

jezusie... roznica przecie wynika z DEIFNICJI trybow DEBUG i RELEASE..

DEBUG: zestaw ustawien kompilatora, w ktorych m.in.:

  • automatycznie dodawane sa 'runtime-checks' np. sprawdzanie przekroczenia zakresu tablicy, wlaczone sa assert'y i wszedzie wstawioen jest pelno 'smiecia' kontrolujacego poprawnosc stosu, blabla..
  • do programu dolaczone sa informacje o numerach linii/aktualnych wyrazeniach jezyka, zeby debugger byl w stanie to sledzic
  • wylaczona jest jakakolwiek optymalizacja
    ..

RELEASE:

  • runtime-checks sa wylaczone
  • asercje sa wylaczone
  • brak debug-info
  • optymalizacje sa wlaczone na stopien max lub prawie-max
    ..

jesli nie wiesz czym sa te terminy, poczytaj o nich, powinno Cie natychmiast olsnic skad sie bierze roznica..
kurcze, jak kompilator Ci (nie)wywali z zagniezdzonej petli wszystkie niezmienniki to juz mozesz (nie)uzyskac kilka rzedow wielkosci czasu..

0

Jedyna rada to wyłączyć optymalizację i liczyć się z tym, że wynik będzie zawyżony.
Zmierz również ile się wykonuje sama pętla i odejmij ten czas od wyniku.

0

Zdaję sobie sprawę z różnic pomiędzy trybami. Naprawdę uważasz, że taka różnica (vide screeny) jest normalna? Ja rozumiem, wzrost wydajności, ale w "prostszej" pętli czas wykonania jest 10000 tysięcy razy krótszy, a w dłuższej - prawie sto milionów.

To jest normalne? Dlaczego w oby wypadkach czas spadł do takiej samej małej wartości? (ten sam test na laptopie - uzyskiwalem wynik 0.0000010 w obu przypadkach).

Oczywiście że wielu rzeczy jeszcze nie wiem, ale nie jestem skończonym idiotą, do którego trzeba się zbliżać wzywając byty transcendentne na pomoc. Proszę o wyrozumiałość. Zwłaszcza, że nadal nie jestem przekonany, że wyniki które uzyskuję, po prostu "powinny takie być i basta".

Kod i screeny wyników:

QueryPerformanceCounter(&start);
    a = 1000000;
    c = a;
    for (c; c > 0; c--)
    {
        a++;
        a = a * c;
        a = a / c;
        b = a;
        b = b - 2;
        a = a - b;
        helper = helper + a;
    }
    QueryPerformanceCounter(&end);
    duration = timeDiff(start, end);
void PomiarDlugi()
{
    int j, i;
    for (j = 0; j < 555; j++)
    {
        for (i = 0; i < 1831500; i++)
            silnia();

    } 
}

void silnia()
{
    int di, ax, cx, bx;
    di = 1;
    cx = 6;
    bx = 1;     //      ;BX to wynik
    do
    {
        ax = bx;
        ax = ax * cx;
        bx = ax;
        cx = cx - 1;
        //cout << "bx = " << bx << endl;
    } while (di != cx);
}
    QueryPerformanceCounter(&start);
    PomiarDlugi();
    QueryPerformanceCounter(&end);
    duration = timeDiff(start, end);

screen1 (release)
screen2 (debug)

<image=http://img247.imageshack.us/img247/6123/debugye9.th.jpg> </url></image> <image=http://img402.imageshack.us/img402/4346/releasevt2.th.jpg></image>
0

LOL, sorry, ale C to nie jest asembler, i jak chcesz zwrocic/przekazac jakies wartosci to powinienes uzyc return/parametrow...

0

Sprawa jest taka - cały ten kod jest bezsensowny i nadmiarowy, przy kompilacji w wersji release po prostu wszystko co niepotrzebne jest wywalane. Wykonujesz operacje bez efektów ubocznych, których wyniki są pomijane - usunięcie tego jest jedną z podstawowych technik optymalizacji.

0

Rzeczywiście wystarczyło wyłączyć w ustawieniach projektu optymalizację ze względu na prędkość. Wcześniej spróbowałem jeszcze tylko zmienić moje funkcje void na int, liczyłem ilość przebiegów forów, aby wynik wyświetlić na ekranie - ale czas był taki sam. Ciekawe, bo oznacza to chyba, że krótki czas jest osiągany w inny sposób niż przez usuwanie "zbędnego" kodu. Ale nie zamierzam już tego drążyć.

Dzięki wszystkim za pomoc.

0

Kod jest nie tylko usuwany ;) Pewnie jak zostaje pusta pętla to zamieniana jest na pojedynczą instrukcję przypisania.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0