webForumDet fria alternativet

CPU load

28 svar · 744 visningar · startad av fluff

fluffMedlem sedan juli 200268 inlägg
#1

Hej.

Jag tänkte snickra ihop nåt litet program som utför 'cpu intensiva' operationer och tar tid på det, för skojs skull :D

Tidtagningen är lätt, men jag lyckas inte komma på nån operation som tar väldigt mycket kraft!

Kör just nu en liten for-sats som dubblar ett tal massa gånger samt skriver ut det, men om man tar bort själva utmatningen till skärmen så går det på 0.0001 sekunder :o

Hur gör man en sådan kraftig operation utan 'utmatning' ? :-)

Jag pratar win32 console-application :)

developerMedlem sedan aug. 2001453 inlägg
#2

Kör en loop och allokera minne på heapen för att sedan direkt lämna tillbaka det.

fluffMedlem sedan juli 200268 inlägg
#3

Oy!

Har du lust/tid att beskriva det närmre?

Förstår inte riktigt vad du menar?

*skyller på dålig kunskap*

PeWMedlem sedan juni 20006 839 inlägg
#4
loop:
     int k = new int
     delete k;

typ...

fluffMedlem sedan juli 200268 inlägg
#5

Aha, har testat lite granna nu.

Tidigare har jag 'klockat' sekundrarna med time() (stop - start tid)

Kom på att det är inte vidare 'precist', har ni nåt tips om ett bättre sätt att tima det hela?

developerMedlem sedan aug. 2001453 inlägg
#6

GetTickCount

developerMedlem sedan aug. 2001453 inlägg
#7

Sedan ska du förstås köra många iterationer i följd och mäta medelvärdet. Att bara köra en sampling ger ett oprecist resultat.

Sang-draxMedlem sedan juli 2002570 inlägg
#8

Använd clock() istället för time(). Det är ANSI-motsvarigheten till GetTickCount.

För mkt hög precision använder man sig av asm:

Denna funktion returnerar antalet cpu-cykler som har gått sedan datorn startades, om du har 1GHz-processor får du alltså en noggrannhet på en nanosekund! (minus anropstiden för funktionen).

inline __int64 Rdtsc64()
{
    unsigned long int LowPart;
    unsigned long int HighPart;
    __asm
    {
        pushad
		cpuid
		rdtsc
		mov	HighPart, edx
		mov	LowPart, eax
		popad
    }

    __int64 value;
    value = ((__int64)HighPart << 32) | LowPart;
    return value;
}
fluffMedlem sedan juli 200268 inlägg
#9

tax!

Jag kör med clock() istället nu, mäter start-tiden, utför lite "new int"'s, mäter stopptiden. stop - start.

Sen kör jag det 5 gånger och tar genomsnittet, funkar rätt bra faktiskt. Är detta 'ett lämpligt' sätt? :)

ps, hur tar man reda på hur många 'mhz' det är på processorn, i visual studio, ds

fluffMedlem sedan juli 200268 inlägg
#10

Sang-Drax, jag använder inte din funktion för jag vill hålla mig till saker som jag iaf kan förstå mig på ;-)

Tack för koden, den kommer komma till användning senare ändå :)

developerMedlem sedan aug. 2001453 inlägg
#11

rdtsc är bra (lättare att använda än GetTickCount eftersom den inte slår runt). Man bör dock bara medveten om att många processorer varierar frekvensen för att spara ström och då fungerar rdtsc dåligt för tidsmätning.

5 gånger är för lite om du vill göra en bra mätning. Kör 5000 istället (det kommer ju gå blixtsnabbt ändå) så får du en bättre noggranhet.

fluffMedlem sedan juli 200268 inlägg
#12

Hmm.

Om jag fått allt rätt nu, så ska jag göra ungefär så här:

int funktion() {

start = Rdtsc64();
loopa "new int" 50000 gånger
stop = Rdtsc64();

return stop-start;
}

loop 5000 gånger:
totala += funktion();

skriva ut totala/5000;

Kraftigt förenklat/ingen-syntax, bara för att visa min tankegång..

ToonsterMedlem sedan feb. 20001 546 inlägg
#13

Du kan även höja prioriteten för programmet för att det ska "belasta" ännu mer

nikoMedlem sedan juni 20022 415 inlägg
#14

Om du helt vill hindra att andra processer stjäl CPU och stör din mätning
så kan du rama in din kod så här:

__asm cli
//Din kod här.
__asm sti

(Funkar bara på Win9x.)

fluffMedlem sedan juli 200268 inlägg
#15

Meh, kunde det inte stått 'funkar endast på WinNT'? :bire

Jag använder inte och beblandar mig inte med Win9x system :r

Marcus EMedlem sedan maj 20021 294 inlägg
#16

fluff skrev:

Jag använder inte och beblandar mig inte med Win9x system

Det ska du vara glad för. Att stänga av avbrottsförfrågningar (cli) kan vara (är) ödesdigert. Hela systemet kraschar antagligen.

fluffMedlem sedan juli 200268 inlägg
#17

Hmmz

Jag har gjort ett litet test-program nu som (gör det jag skrev ovan), en loop på att skapa massa int's.

sen en loop på loopen som skapar ints, för att sedan ta medvärdet på loopen som loopade int'sen :)

använder då clock() som 'start' och 'stop' tider.

Grejen är att när jag gör detta på min 1.2Ghz win2k maskin, får jag ca 12000 'ticks', kör jag det på min oerhört gamla linux maskin (333mhz) så får jag 6000 ticks. (kompilerat med gcc)

Hur fasen kommer det sig att den gamla häcken är snabbare? :O

(det tog märkbart mycket längre tid också, flera minuter för linux-datorn medans ca 40 sekunder på win2k....)

nikoMedlem sedan juni 20022 415 inlägg
#18

fluff skrev:

Hur fasen kommer det sig att den gamla häcken är snabbare? :O

Skillnader i hur "new/delete" är implementerade på Linux o Win2k, kanske?

"new" är en wrappning av "malloc" som är en wrappning av ett systemanrop
som i sin tur gör nån request till kernelns minneshanterare osv .. Det finns ju
inget som säger att det totala antalet instruktioner för allt detta i
slutändan skulle vara lika mellan två operativ. Fast skillnaden känns ganska stor ..

Marcus E skrev:

Att stänga av avbrottsförfrågningar (cli) kan vara (är) ödesdigert. Hela systemet kraschar antagligen.

Inte om du vet vad du gör. Varenda drivis på 9X (och NT/2000) gör så med jämna mellanrum (indirekt).

developerMedlem sedan aug. 2001453 inlägg
#19

niko skrev:

Marcus E skrev:

Att stänga av avbrottsförfrågningar (cli) kan vara (är) ödesdigert. Hela systemet kraschar antagligen.

Inte om du vet vad du gör. Varenda drivis på 9X (och NT/2000) gör så med jämna mellanrum (indirekt).

Du vet då säkert också att ändra IRQL är något man inte gör i vanliga applikationer i usermode, utan just drivrutiner i kernelmode.

developerMedlem sedan aug. 2001453 inlägg
#20

niko skrev:

Skillnader i hur "new/delete" är implementerade på Linux o Win2k, kanske?

"new" är en wrappning av "malloc" som är en wrappning av ett systemanrop
som i sin tur gör nån request till kernelns minneshanterare osv .. Det finns ju
inget som säger att det totala antalet instruktioner för allt detta i
slutändan skulle vara lika mellan två operativ. Fast skillnaden känns ganska stor ..

new behöver inte använda malloc (även om det ofta är implementerat så).

Runtimen (som följer med utvecklingsverktyget, inte operativsystemet) kan välja att låta varje allokering/deallokering leda till ett OS-anrop för att allokera/deallokera minne. Alternativt kan runtimen ha en smartare heap-hanterare som håller reda på heap-block, vilket leder till att new/malloc går mycket snabbare. I Microsoft-miljö kan man slå på small block heap för att uppnå detta (_set_sbh_threshold).

Fluff, om du använder olika kompilatorer bör du vara särskilt nogrann med att du har liknande optimeringsflaggor påslagna. Kör du exempelvis Microsofts Debug-bygge kommer den lägga på en massa kod för att kontrollera att du inte skriver utanför tillåtna block, och det har förstås en märkbart negativ påverkan på prestanda.

Genererad på 386 ms · cache AV · v20260730165559-full.f96bc7eb