[C++] Platformonafhankelijke miliseconden

Pagina: 1
Acties:

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Ik ben bezig met het omzetten van een java app naar c++, om eens te zien of het veel scheelt qua performance. In algemene zin valt het omzetten me reuze mee, al zijn er wat zaken die anders moeten: het feit dat C++ geen named loops heeft verbaasde me bijvoorbeeld.

Goed, in java kan ik gemakkelijk het aantal miliseconden sinds jan 1970 opvragen, in C++ blijkbaar niet, standaard geloof ik alleen precisie tot in seconden. Ik gebruik in mijn java app een Stopwatch klasse waarmee ik (globaal) kan meten hoeveel tijd bepaalde onderdelen kosten. Deze klasse meet in miliseconden, en dit wil ik nu dus ook in C++ kunnen doen.

Is er een platformonafhankelijke manier om dit op te lossen?

Ik ben op de hoogte van gettimeofday() onder linux, en las net ook wat WIN32-specifieke oplossingen, maar zoek eigenlijk een platformonafhankelijke oplossing, zodat ik mijn applicatie zo generiek mogelijk kan houden, net als de java variant.

Ik zat net al te kijken op boost.org, aangezien die wel een aardig uitgebreide library onderhouden, maar ben er nog niet goed in thuis.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
"named loops"?

Waarom wil je performance eigenlijk platform-onafhankelijk meten?

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 25-09-2023
"named loops"?
Topic starter bedoelt hierbij dat je loops een naampje kan geven, zodat je uit een bepaalde loop kan breaken / continue'en.

Je kan je programma's ook meten m.b.v. GetTickCount. Of je dan nog een vergelijking kan maken met java hangt er vanaf of je dat naar seconden kan omrekenen.

Maar waarom is het zo belangrijk dat je op de miliseconde nauwkeurig meet? Als de performance zo belangrijk is dan herhaal je het zo wie zo heel erg veel keer. Herhaal dan zo'n experiment genoeg keer zodat je een paar minuten bezig bent. Dan zijn hele seconden vast wel naukeurig genoeg.

[ Voor 63% gewijzigd door Infinitive op 06-03-2004 00:29 ]

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


  • ATS
  • Registratie: September 2001
  • Laatst online: 12-02 13:46

ATS

Lang niet elk systeem kan miliseconden leveren, en voor benchmarks zijn enkele runs idd toch te onbetrouwbaar.
Platformonafhankelijkheid bereik je via een toolkit die dit ondersteund. Qt bijvoorbeeld.

My opinions may have changed, but not the fact that I am right. -- Ashleigh Brilliant


  • B-Man
  • Registratie: Februari 2000
  • Niet online
De twee platforms waar ik nu op draai zijn windows 2000 en linux, dus ik denk dat ik support voor die twee platforms inbouw.

Waarom ik in miliseconden wil meten? Omdat ik niet enkel de perfomance van een algoritme wil meten, maar tijdens het draaien van de applicatie ook perfomance wil kunnen meten, uitgesplitst naar deelprocessen.

Ik heb de java applicatie die ik nu draai al erg ver geoptimaliseerd, maar aangezien deze voor een groot deel met strings bezig is, en ze wijzigt, wil ik eens kijken hoeveel sneller C++ nu echt is met strings.

Overigens laat ik het spul nu al 10.000 keer loopen, en dat weer nested in een loop die 10 keer draait, om een gemiddelde te kunnen berekenen over de 10 runs, dit met name voor java, aangezien de VM niet meteen de eerste run optimaliseert. Ik print van alle 10 de runs de performance, wat in het geval van java overigens ook duidelijk laat zien wanneer hotspot begint te werken.

Maar goed, ik zal de loops nog wat vaker laten draaien zodat ik het in seconden kan meten, en dan kan vergelijken hoe de perfomance is relatief aan java. Als het verschil klein is, ga ik de applicatie niet verder omzetten c++.

Hoe zet ik overigens named loops om naar c++? Ik gebruik named loops omdat ik dan vanuit de binnenste lus een "continue <naam buitenste lus>" kan gebruiken, moet ik hiervoor in C++ een goto gebruiken in combinatie met het ophogen van de teller in mijn for-loop?

  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

B-Man schreef op 05 maart 2004 @ 20:15:
Is er een platformonafhankelijke manier om dit op te lossen?
Nope.
Ik ben op de hoogte van gettimeofday() onder linux, en las net ook wat WIN32-specifieke oplossingen, maar zoek eigenlijk een platformonafhankelijke oplossing, zodat ik mijn applicatie zo generiek mogelijk kan houden, net als de java variant.
Die is er AFAIK niet. Indien je alleen wil meten hoe lang iets duurt kun je de rdtsc instructie gebruiken (aka de Pentium tick counter). Je krijgt dat een waarde in clockticks, en da's vrij nauwkeurig.

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22-05 16:53
B-Man schreef op 06 maart 2004 @ 13:11:
Hoe zet ik overigens named loops om naar c++? Ik gebruik named loops omdat ik dan vanuit de binnenste lus een "continue <naam buitenste lus>" kan gebruiken, moet ik hiervoor in C++ een goto gebruiken in combinatie met het ophogen van de teller in mijn for-loop?
Je kunt alleen uit de binnenste loop springen met break.

Normaal gesproken mag je goto natuurlijk niet gebruiken :)

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

farlane schreef op 06 maart 2004 @ 13:51:
Normaal gesproken mag je goto natuurlijk niet gebruiken :)
Da'r vrij grote nonsense als je het mij vraagt. In specifieke gevallen is een goto aan te raden, vooral als het gata om errorhandling in een functie.

  • MisterData
  • Registratie: September 2001
  • Laatst online: 21:51
B-Man schreef op 06 maart 2004 @ 13:11:
[..] Omdat ik niet enkel de perfomance van een algoritme wil meten, maar tijdens het draaien van de applicatie ook perfomance wil kunnen meten, uitgesplitst naar deelprocessen.

Ik heb de java applicatie die ik nu draai al erg ver geoptimaliseerd, maar aangezien deze voor een groot deel met strings bezig is, en ze wijzigt, wil ik eens kijken hoeveel sneller C++ nu echt is met strings.

Overigens laat ik het spul nu al 10.000 keer loopen, en dat weer nested in een loop die 10 keer draait, om een gemiddelde te kunnen berekenen over de 10 runs, dit met name voor java, aangezien de VM niet meteen de eerste run optimaliseert. Ik print van alle 10 de runs de performance, wat in het geval van java overigens ook duidelijk laat zien wanneer hotspot begint te werken.
En als je iets van een profiler ofzo gebruikt? Dan kun je mooi zien hoe lang het programma met bepaalde dingen bezig is en kun je optimaliseren... Google maar es op [google=GlowCode]GlowCode[/code], dat is zo'n profiler waarmee je C/C++ programma's kunt profilen. Ik geloof da ter bij bepaalde versies van MSVC++ ook een Profiler zat, maar dat weet ik niet zeker :)

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Hmmm, ik heb nu een string replace functie geschreven die direct met char* werkt, om te kijken hoe snel c++ is in verhouding tot exact dezelfde routine in java, en de resultaten zijn eigenlijk wel interessant:

(Ik heb mijn routine 50.000 keer laten draaien)

C++: 12 seconden
Java: 20 seconden

Ik ga nog wat delen van mijn java app in C++ maken, om te zien of het verschil daar ook zichtbaar is.

-- edit:

Met optimalisatie aan (GNU gcc), draait de code zelfs in 9 seconden, nog sneller dus.

[ Voor 12% gewijzigd door B-Man op 07-03-2004 21:40 ]


  • Count
  • Registratie: Augustus 2000
  • Laatst online: 10-08-2023
igmar schreef op 06 maart 2004 @ 17:04:
[...]


Da'r vrij grote nonsense als je het mij vraagt. In specifieke gevallen is een goto aan te raden, vooral als het gata om errorhandling in een functie.
Met C++ zijn exceptions toch een heel stuk beter dan goto.

Kort gezegd; als je goto gebruikt dan heb je een suboptimale oplossing voor je probleem.

Great minds think in parallel gutters.


Verwijderd

Ik gebruik in een project dat ik zelf aan het maken ben ook een lus, waarvan ik de miliseconden wil meten. Ik gebruik hiervoor clock() uit <time.h> Volgens de docu uit Visual Studio is dit een ANSI functie. Hier is de het stukje uit visual studio
Run-Time Library Reference

clockSee Also
Time Management Routines | difftime | time
Requirements
Routine Required header Compatibility
clock <time.h> ANSI, Win 98, Win Me, Win NT, Win 2000, Win XP

For additional compatibility information, see Compatibility in the Introduction.

Libraries

All versions of the C run-time libraries.
Calculates the wall-clock time used by the calling process.

clock_t clock( void );
Return Value
The elapsed wall-clock time since the start of the process (elapsed time in seconds times CLOCKS_PER_SEC). If the amount of elapsed time is unavailable, the function returns ?1, cast as a clock_t.

Remarks
The clock function tells how much time the calling process has used. A timer tick is approximately equal to 1/CLOCKS_PER_SEC second. In versions of Microsoft C before 6.0, the CLOCKS_PER_SEC constant was called CLK_TCK.

Requirements
Routine Required header Compatibility
clock <time.h> ANSI, Win 98, Win Me, Win NT, Win 2000, Win XP

For additional compatibility information, see Compatibility in the Introduction.

Libraries

All versions of the C run-time libraries.

Example
/* CLOCK.C: This example prompts for how long
* the program is to run and then continuously
* displays the elapsed time for that period.
*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void sleep( clock_t wait );

void main( void )
{
long i = 600000L;
clock_t start, finish;
double duration;

/* Delay for a specified time. */
printf( "Delay for three seconds\n" );
sleep( (clock_t)3 * CLOCKS_PER_SEC );
printf( "Done!\n" );

/* Measure the duration of an event. */
printf( "Time to do %ld empty loops is ", i );
start = clock();
while( i-- )
;
finish = clock();
duration = (double)(finish - start) / CLOCKS_PER_SEC;
printf( "%2.1f seconds\n", duration );
}

/* Pauses for a specified number of milliseconds. */
void sleep( clock_t wait )
{
clock_t goal;
goal = wait + clock();
while( goal > clock() )
;
}

Output
Delay for three seconds
Done!
Time to do 600000 empty loops is 0.1 seconds

See Also
Time Management Routines | difftime | time


--------------------------------------------------------------------------------

Send feedback to Microsoft

© 2001 Microsoft Corporation. All rights reserved.

  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

Count schreef op 07 maart 2004 @ 23:26:
Met C++ zijn exceptions toch een heel stuk beter dan goto.

Kort gezegd; als je goto gebruikt dan heb je een suboptimale oplossing voor je probleem.
In C++ in de meeste gevallen wel ja. Helaas zijn exceptions nogal platform en compilerafhankelijk, dus niet in alle gevallen een optie.

  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

Verwijderd schreef op 08 maart 2004 @ 13:24:
Ik gebruik in een project dat ik zelf aan het maken ben ook een lus, waarvan ik de miliseconden wil meten. Ik gebruik hiervoor clock() uit <time.h> Volgens de docu uit Visual Studio is dit een ANSI functie. Hier is de het stukje uit visual studio
clock() meet het aantal scheduler slots dat een process tot nu toe heeft gebruikt, en is geen absolute tijdsmeting. Verder is clock() een grove benadering, en ik denk voor de TS niet bruikbaar (het was voor mij iig niet bruikbaar).

[ Voor 5% gewijzigd door igmar op 08-03-2004 13:34 ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22-05 16:53
Waarom gebruik je eigenlijk geen platform afhankelijke code tussen #ifdef..... #endif blokken ?

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

igmar schreef op 08 maart 2004 @ 13:31:
[...]
In C++ in de meeste gevallen wel ja. Helaas zijn exceptions nogal platform en compilerafhankelijk, dus niet in alle gevallen een optie.
Maar goto maakt in ieder geval op ieder platform en compiler ranzige, lelijke en ononderhoudbare code, dus nooit een optie :Y)

Professionele website nodig?


  • B-Man
  • Registratie: Februari 2000
  • Niet online
Ik gebruik nu gewoon een goto, ranzig of niet, volgens mij maakt het in deze code niet zoveel uit. Curry: als je je geroepen voelt om deze code "op te schonen", ga je gang ;)

Hieronder een stukje uit mijn replace functie, waairn ik nu een goto gebruik. Deze code meet hoeveel matches met "from" er zijn in het char array "orig_in".
De variable "locs" bevat de locatie van de matches, en de variable "h" houdt het aantal hits bij.
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
char* replace(char* orig_in, const char* from, const char* to) {

        if (strlen(from) == 0) return orig_in;
            
        // Find matches

        const int fromLength = strlen(from);
        const int toLength = strlen(to);
        const int diff = toLength - fromLength;
        const int tMax = strlen(orig_in) - fromLength + 1;

        int h = 0, i = -1, j;
        const char fromCs = from[0];
        
        first: while (++i < tMax) {
            if (orig_in[i] != fromCs) continue;
            
            j = 1; 
            while (j < fromLength)
                if(orig_in[i+j] != from[j++]) goto first;
            
            locs[h++] = i;
            i+=fromLength-1;
        }


Farlane: ja, dat ga ik ook doen. Ik gebruik nu time() om met een groot aantal herhalingen in seconden te kunnen vergelijken, maar wil in een later stadium wel miliseconden kunnen meten.

[ Voor 14% gewijzigd door B-Man op 08-03-2004 15:23 ]


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

B-Man schreef op 08 maart 2004 @ 15:21:
Ik gebruik nu gewoon een goto, ranzig of niet, volgens mij maakt het in deze code niet zoveel uit. Curry: als je je geroepen voelt om deze code "op te schonen", ga je gang ;)

Hieronder een stukje uit mijn replace functie, waairn ik nu een goto gebruik. Deze code meet hoeveel matches met "from" er zijn in het char array "orig_in".
De variable "locs" bevat de locatie van de matches, en de variable "h" houdt het aantal hits bij.
Ik snap geen ruk van je code. 'locs' wordt nergens gedeclareerd, en volgens je eigen beschrijving doe je dus nergens een replace in de functie 'replace'. Ik weet wel dat je godsgruwelijk inefficient bezig bent :) Doe eens toelichten dan zal ik straks eens hobbyen :Y)

Professionele website nodig?


  • Sjaaky
  • Registratie: Oktober 2000
  • Laatst online: 26-05 01:17
Ik voel een herhaling van dit topic in C(++) aankomen...

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Sjaaky schreef op 08 maart 2004 @ 15:57:
Ik voel een herhaling van dit topic in C(++) aankomen...
Haha, goed gezien ;)

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
static int* locs = new int[16000];

char* replace(char* orig_in, const char* from, const char* to) {

        if (strlen(from) == 0) return orig_in;
            
        // Start replace 

        const int fromLength = strlen(from);
        const int toLength = strlen(to);
        const int diff = toLength - fromLength;
        const int tMax = strlen(orig_in) - fromLength + 1;

        int h = 0, i = -1, j;
        const char fromCs = from[0];
        
        first: while (++i < tMax) {
            if (orig_in[i] != fromCs) continue;
            
            j = 1; 
            while (j < fromLength)
                if(orig_in[i+j] != from[j++]) goto first;
            
            locs[h++] = i;
            i+=fromLength-1;
        }
        
        char* out;
        
        if (h == 0) return orig_in;
        else {
            if (diff == 0)  out = orig_in;
            else            out = new char[strlen(orig_in) + (h * diff) + 1];
        }
        
        int lhe = 0, po = 0, size = 0; // last hit end, pos out, size of text between

        for (i = 0; i < h; i++) {
            if (diff != 0) {
                size = locs[i]-lhe-1;
                if (i == 0 && locs[i]>0) { // text before first
                    strncpy(out, orig_in, locs[i]);
                    po = locs[i];
                } else if (size>0) { // Between this one and prev
                    strncpy(out+po, orig_in+lhe+1, size);
                    po += size;
                }
            }
            if (diff == 0) po = locs[i];

            // Now replace tag 
            strncpy(out+po, to, toLength);
            po += toLength;

            lhe = locs[i] + fromLength - 1;
        }
        
        if (diff != 0) {// Copy all after last tag, including null terminator
            strcpy(out+po, orig_in+lhe+1);
        }
                
        return out;
    }


Ja, dit is vrijwel dezelfde code als in het Java-topic dat net genoemd werd. Als er efficientere manieren zijn om dit in c++ te doen, hoor ik het graag.
Deze functie is in java erg snel.

C++:
1
2
3
4
5
6
7
8
9
10
11
string replaceNew(string &orig_in, const char* from, const char* to) {
    
    const int fromLength = strlen(from);
    int position = orig_in.find(from);
    while(position != string::npos) {
        orig_in.replace(position, fromLength, to);
        position = orig_in.find(from, position);
    }
    
    return orig_in;
}

vond ik in ieder geval godsgruwelijk traag.

  • B-Man
  • Registratie: Februari 2000
  • Niet online
curry684 schreef op 08 maart 2004 @ 15:34:
[...]

Ik snap geen ruk van je code. 'locs' wordt nergens gedeclareerd, en volgens je eigen beschrijving doe je dus nergens een replace in de functie 'replace'. Ik weet wel dat je godsgruwelijk inefficient bezig bent :) Doe eens toelichten dan zal ik straks eens hobbyen :Y)
Ik gaf ook al aan in mijn post dat het een stukje uit mijn functie is B)
Ik heb nu in ieder geval de gehele functie geplaatst.

Je hebt mijn interesse in ieder geval gewekt, dus als je er eens naar kan kijken, en mogelijk optimaliseren, graag :).

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
igmar schreef op 08 maart 2004 @ 13:31:
[...]
In C++ in de meeste gevallen wel ja. Helaas zijn exceptions nogal platform en compilerafhankelijk, dus niet in alle gevallen een optie.
Sorry?
Hoe dan wel?

Er is maar een berucht issue, en dat zijn exception specs. Die zijn in de praktijk overbodig, vandaar dat niemand zich er druk overmaakt: try catch X en throw X werken zonder problemen.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein

Pagina: 1