12. oktober 2000 - 09:33
Der er
17 kommentarer og 1 løsning
Jonglere med milisekunder i Borland C++ Builder
Jeg vil gerne lave en program stump der kan fortælle mig hvor lang tid det tager at løbe f.eks en løkke igennem. Jeg forestiller mig at det skal være noget i retning af: (pseudokode) Start = now i milisekunder Her er den løkke der skal løbes igennem Slut = now i milisekunder Varighed = Slut - Start
Annonceindlæg fra Publicis Sapient
12. oktober 2000 - 09:36
#1
int Start = GetTickCount(); for (int i=0; i<1000000;++i); int Slut = GetTickCount() - Start; i slut variablen hat du nu den tid der er gået i millisekunder Jens B
12. oktober 2000 - 09:36
#2
Det var så et svar.
12. oktober 2000 - 10:18
#3
Den hårde fysisk vej er at se på den enkelte kommando og hvordan borland compileren kompilerer den enkelte kode over i asm, og se her hvor mange linjer den fylder, en linje er så en clockcycle.
12. oktober 2000 - 10:21
#4
Et lille kig i online manualen har aldrig skadet nogen :-) Dette virker ihvertfald. int main(void) { clock_t start, end; start = clock(); long i = 6000000L; while (i--) { i++; i--; } end = clock(); printf(\"The time was: %f\\n\", (end - start) / CLK_TCK); return 0; } >>borrisholt Jeg tjekker lige din løsning.
12. oktober 2000 - 10:26
#5
>>borrisholt - med din løsning får jeg blot 0.0000 sekunder, eller 2.121996e-313 hvilket vist ikke er helt korrekt
12. oktober 2000 - 10:33
#6
Det kan jeg nu ikke lige forstå .... Jeg har ikke C Builder her .. men \"kun\" en Delphi. Men mon ikke selv du kan porte : Det her virker : procedure TForm1.Button2Click(Sender: TObject); var Start,Stop : DWORD; i : Integer; begin Start := getTickCount; for i:= 0 to 10000 do Caption := IntToStr(i); Stop := getTickCount - Start; Caption := IntToStr(Stop) + \'Millisekunder\'; end; Det har jeg lige tested jens B
12. oktober 2000 - 10:46
#7
Det kan jo rent faktisk godt være at 10000 gennemløb af ovenstående forholdsvis simple løkkestruktur tager under 1 millisekund og at 0.0 derfor er korrekt. Ligepræcis en for løkke kan i ASM forkortes til stort set to instruktioner: DECR, JNZ, hvis blot programmet starter med at loede I til f.eks. AX registret.
12. oktober 2000 - 16:01
#8
OK borrisholt det fungerer også, men problemet har udviklet sig til et konverteringsproblem. Når jeg nu har lavet 10000 gennemløb vil jeg gerne regne ud hvor lang tid det tog pr gennemløb, hvordan laver jeg en sådan division med en præcision på ca 10 betydende cifre.
12. oktober 2000 - 16:09
#9
Så skal du bruge en mere nøjagtig tæller : prøv det her : procedure TForm1.Button1Click(Sender: TObject); var i : Integer; Start, Stop, Freq: Int64; begin QueryPerformanceCounter(Start); for i:= 0 to 10000 do begin Caption := IntToStr(i); end; QueryPerformanceCounter(Stop); QueryPerformanceFrequency(Freq); Caption := \'Tid Brugt : \' + floatToStr((Stop - Start) / Freq) + \'Sekunder\'; end; Så kan du jo selv dividere og gøre ved på det bag efter .... Er det ikke nøjagtigt nok må vil jo tælle clock cycels ... Men den tid den sorg ... Jens B
16. oktober 2000 - 10:23
#10
Følgende giver en EAccessViolation ! Hvad er der galt ? _LARGE_INTEGER *Start, *Stop, *Freq; QueryPerformanceCounter(Start); for (int i = 0; i< 10000; i++ ) { Memo1->Lines->Add( IntToStr(i) ); } QueryPerformanceCounter(Stop); QueryPerformanceFrequency(Freq); Memo1->Lines->Add(\"Tid Brugt : \" + FloatToStr((Stop->HighPart - Start->HighPart) / Freq->HighPart) + \"Sekunder\");
18. oktober 2000 - 10:16
#11
nu får jeg en compiler fejl: Kan ikke konvertere en _large_integer til en _large_integer ???
18. oktober 2000 - 10:55
#12
problemert er et kombalitets problem mellem en record der ser sådan ud : _LARGE_INTEGER = record case Integer of 0: ( LowPart: DWORD; HighPart: Longint); 1: ( QuadPart: LONGLONG); end; og så en alm 64 bits integer: __int64 QueryPerformance funktionerne forventer en __int64 og ikke en LARGE_INTEGER eventuelt kan du laven en type definition alla den her : typedef _LARGE_INTEGER TLargeInteger; også nede i funktions kaldene overstyre det til en 64bits integer du ved alla _LARGE_INTEGER *Start, *Stop, *Freq; QueryPerformanceCounter((__int64)Start); for (int i = 0; i< 10000; i++ ) { Memo1->Lines->Add( IntToStr(i) ); } Jens B
18. oktober 2000 - 11:32
#13
Går det hele så helt i u-fisk for dig må du jo tælle clock cykler og regne lidt på dem. Til det formål vil jeg anbefalde det følgende : #include \"stdafx.h\" #include \"windows.h\" union TTimeStamp { __int64 Whole; struct { int Lo; int Hi; }Other; }; __int64 GetTimeStamp() { TTimeStamp TimeStamp; __asm { _emit 0x0f _emit 0x31 mov TimeStamp.Other.Lo, eax mov TimeStamp.Other.Hi, edx } return TimeStamp.Whole; } double GetCpuSpeed() { const DelayTime = 500; int TimerLo, TimerHi; int PriorityClass = GetPriorityClass( GetCurrentProcess() ); int Priority = GetThreadPriority( GetCurrentThread() ); SetPriorityClass(GetCurrentProcess() , REALTIME_PRIORITY_CLASS); SetThreadPriority(GetCurrentThread() , THREAD_PRIORITY_TIME_CRITICAL); SleepEx(10, false); __asm { _emit 0x0f _emit 0x31 mov TimerLo, eax mov TimerHi, edx } SleepEx(DelayTime, false); __asm { _emit 0x0f _emit 0x31 sub eax, TimerLo sbb edx, TimerHi mov TimerLo, eax mov TimerHi, edx } SetThreadPriority(GetCurrentThread() , Priority); SetPriorityClass(GetCurrentProcess() , PriorityClass); return (double) TimerLo / (1000 * DelayTime); } int main(int argc, char* argv[]) { __int64 Start, Stop; double TotalSeconds; double CPUSpeed = GetCpuSpeed() ; for(;;) { Start = GetTimeStamp(); int j = 0; for (int i= 0; i<1000000; ++i) { ++j *=3 %373272323; j /=3; j *=i % 33; } Stop = GetTimeStamp(); TotalSeconds = (Stop - Start) / (CPUSpeed * 1e6); printf(\"Tid Brugt : %f Sekunder\\n\", TotalSeconds); } return 0; } Jens B
18. oktober 2000 - 11:37
#14
orv ja .. hvrofor sagde du ikke det inden jeg postede ? I C++ Builder skal du erstatte _emit med db Det kunne du godt have sagt ! :) jens B
20. oktober 2000 - 13:43
#15
>>borrisholt Jeg tester lige din sidste løsning. hav venligst lidt tålmodighed.
30. oktober 2000 - 16:19
#16
ckrame >> \"hav venligst lidt tålmodighed\" nu er der gået 10 dage ... Hvor længe skal du bruge på at teste noget så simplet ? Jens B
30. oktober 2000 - 16:23
#17
Jammen jeg er ikke så hurtig :-) Nå men vi besluttede at benytte den første løsning selvom den ikke er så præcis igen, så jeg har ikke lige fået testet den sidste løsning. Du skal dog have dine point alligevel - tak for hjælpen
30. oktober 2000 - 16:25
#18
:o) Jens B
Kurser inden for grundlæggende programmering