Προς το περιεχόμενο

χρόνος εκτέλεσης προγράμματος


yincyun

Προτεινόμενες αναρτήσεις

Δημοσ.

Καλησπέρα σας. μια ερώτηση -ίσως σε μερικούς φανεί γελοία :)

 

Πως μπορώ να εμφανίσω το χρόνο εκτέλεσης ενός προγράμματος C++??

 

compiler devc++

Δημοσ.

το βρήκα.

>
#include <time.h>

int main()
{
	
clock_t start, end;
double cpu_time_used;
start = clock();

... /* Do the work. */

end = clock();
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC; 
cout<<"o xronos ektelesis tou programmatos einai : "<<cpu_time_used;


}

Δημοσ.

Η clock δεν είναι καλή λύση.

Είναι ανακριβής, ειδικά για μικρούς χρόνους εκτέλεσης μπορεί να δίνει ότι να 'ναι.

 

 

Το ζήτημα αυτό έχει ξανασυζητηθεί στο παρελθόν.

Σε περιβάλλον Windows υπάρχουν οι λεγόμενοι high resolution timers που είναι εξαιρετικά ακριβείς και

είναι το de facto για ακριβή χρονομέτρηση. Ένα παράδειγμα χρήσης τους είναι ως εξής :

 

>LARGE_INTEGER liStart, liEnd, liFreq; 

       // Get High-Resolution Timer frequency and mark code begin with HRes Timer.
       QueryPerformanceFrequency(&liFreq)); 
       QueryPerformanceCounter(&liStart)); 


       /*    .... CALCLULATIONS ....   */ 


       // Mark code end with HRes Timer.  
       QueryPerformanceCounter(&liEnd)) ; 

   
       // Calculate HRes difference using High-Resolution Timer freq. 
       printf("%.2Lf'' with FREQ=%Ldn", (long double)(liEnd.QuadPart - liStart.QuadPart) / liFreq.QuadPart, liFreq.QuadPart); 

       // Give the Raw HRes Timers results to user. 
       printf("Raw Count %Ld (no FREQ adj.)n", liEnd.QuadPart - liStart.QuadPart);

 

Nα και μερικές εξηγήσεις :

Για ακριβείς χρονικές μετρήσεις πρέπει να χρησιμοπoιηθεί το χρονόμετρο απόδοσης (performance timer).

Λέγεται και μετρητής απόδοσης (performance counter).

 

Kαταρχήν πρέπει να γίνει η προσάρτηση #include<windows.h> .

O μετρητής απόδοσης μετρά σε μονάδες που λέγονται counts.

Η τρέχουσα τιμή της ώρας μπορεί να ληφθεί με τον μετρητή απόδοσης μετρημένη σε counts χρησιμοποιώντας την

συνάρτηση QueryPerformanceCounter ως εξής :

 

__int64 prevTimeStamp = 0;

QueryPerformanceCounter((LARGE_INTEGER*)&prevTimeStamp);

 

Αυτή η συνάρτηση επιστρέφει την τρέχουσα ώρα μέσω του ορίσματος prevTimeStamp που είναι ένας 64 bit ακέραιος.

Πρακτικά η χρήση της έγκειται στο να λαμβάνονται δυο τιμές σε διαφορετικά διαστήματα - προφανώς στην αρχή και το

τέλος κάποιου υπολογισμού - και να αφαιρείται η πρώτη τιμή από την δεύτερη για να βρεθεί σε counts ο χρόνος που παρήλθε.

Κάπως έτσι :

 

__int64 A = 0;

QueryPerformanceCounter((LARGE_INTEGER*)&A);

 

/* computations */

 

__int64 B = 0;

QueryPerformanceCounter((LARGE_INTEGER*)&B );

 

Ο χρόνος που απαιτείται για την περάτωση των υπολογισμών είναι C=Β-Α μετρημένος σε counts.

Η μονάδα count δεν είναι άμεσα εποπτική. Πρέπει να μετατραπεί σε μια χρονική μονάδα που να έχει πρακτικό νόημα όπως το sec.

Σε αυτό μπορεί να χρησιμοποιηθεί μια άλλη συνάρτηση API , η QueryPerformanceFrequency, που δίνει την συχνότητα του

μετρητή απόδοσης σε counts/sec. H συνάρτηση αυτή καλείται ως εξής :

 

__int64 cntsPerSec= 0;

QueryPerformanceFrequency((LARGE_INTEGER*)&cntsPerSec);

 

όπου η μεταβλητή cntsPerSec είναι όπως είπα counts/sec. Το αντίστροφο του cntsPerSec δίνει πόσα sec αντιστοιχούν σε κάθε count :

 

float secsPerCnt = 1.0f / (float) cntsPerSec;

 

και είναι ο παράγοντας μετατροπής. Έτσι , ο χρόνος που δίνει η QueryPerformanceCounter μετρημένος σε counts, μετατρέπεται

σε sec πολλαπλασιάζοντάς τον με secsPerCnt :

 

valueInSecs = valueInCounts * secsPerCnt;

 

οπότε μετατρέπεται ο χρόνος από μονάδες counts σε sec.

 

Επισημαίνεται επίσης ότι η συνάρτηση QueryPerformanceCounter επιστρέφει ένα τύπο BOOL. Ειδικότερα, true αν ο μετρητής απόδοσης

υπάρχει και false αν δεν υπάρχει. Οι Pentium και οι μεταγενέστερες αυτών cpus έχουν τον μετρητή απόδοσης ενώ άλλοι επεξεργαστές δεν

είναι βέβαιο (συνεπώς κατά την κλήση των συναρτήσεων πρέπει να γίνεται έλεγχος).

Η εναλλακτική σίγουρη λύση είναι η χρήση της συνάρτησης timeGetTime που όμως δεν είναι τόσο ακριβής.

 

Eίναι ενδιαφέρον ότι ο χρόνος που απαιτείται για να σχεδιαστεί ένα frame (frame time), σε millisec ας πούμε,

είναι μια διαφορετική ποσότητα από τα FPS (αν και μπορεί να ληφθεί από αυτά).

Στην πράξη, ο frame time είναι πιο αντιπροσωπευτικός και χρήσιμος από τα FPS παρόλο που δεν είναι γνωστό στον πολύ κόσμο - ειδικά στους gamers !

Με τον frame time άμεσα φαίνεται η αύξηση/μείωση στον χρόνο που απαιτείται για να σχεδιαστεί ένα frame, αντίθετα με τα FPS διότι η καμπύλη των FPS δεν είναι γραμμική.

 

-

Δημοσ.

V.I.Smirnov εχω μια απορια σχετικα μετα παραπανω που εγραψες. Τα counts που καταμετρα η QueryPerformanceCounter ειναι τα ιδια (περιπου) σε καθε υπολογιστη κανοντας π.χ. παυση 1 δευτερολεπτου ή εχει σχεση με την ταχυτητα του υπολογιστη;

Δημοσ.

Οι κοινές συναρτήσεις χρονομέτρησης όπως η clock() βασίζονται σε ένα χρονικό διάστημα μέτρησης που έχει διάρκεια περίπου 10-15 msec.

Για χρόνους εκτέλεσης τέτοιας τάξης δεν είναι ακριβείς.

 

Αντίθετα, οι παραπάνω βασίζονται στον λεγόμενο 64-bit Time Stamp Counter (TSC) του επεξεργαστή

που μετρά το πλήθος των κύκλων από την στιγμή της εκκίνησης του υπολογιστή.

 

Η QueryPerformanceCounter() δίνει την τιμή που έχει ο TSC την στιγμή που καλείται.

Δεδομένου των GHz που έχουν οι σημερινές cpus, ο ΤSC αναβαθμίζεται σε πολύ πυκνότερα διαστήματα από ότι με την clock() ,

γι' αυτό είναι πολύ ακριβέστερη.

Λαμβάνεται μια τιμή ΔΤ :

- αν την μετρηθεί με την clock() έχει σφάλμα Α, δηλ. ΔΤ + - Α

- αν την μετρηθεί με την QueryPerformanceCounter() έχει σφάλμα Β<<Α, άρα το ΔΤ είναι γνωστό με πολύ λγότερο λάθος.

Εφόσον ένας ταχύτερος επεξεργαστής εκτελεί περισσότερους κύκλους στον ίδιο χρόνο από έναν βραδύτερο και ο TSC μετρά κύκλους,

συμπεραίνω ότι η QueryPerformanceCounter() σχετίζεται με την ταχύτητα του επεξεργαστή και ότι στον ταχύτερο θα

μετρήσει περισσότερους κύκλους.

 

Το θέμα της σωστής χρονομέτρησης δεν τελειώνει εδώ.

Τα σημερινά λειτουργικά έχουν προεκτοπιστική πολυδιεργασία. Αυτό σημαίνει ότι για την σωστή εύρεση του χρόνου που

διαρκεί ένα πρόγραμμα ή ένας υπολογισμός πρέπει να μετρηθεί ο χρόνος που αφιερώνει (scheduled time) το λειτουργικό

στο συγκεκριμένο νήμα ή την διεργασία που το εκτελεί. Για να γίνει όπως πρέπει αυτό, τα Windows έχουν τις συναρτήσεις

GetProcessTimes(), GetThreadTimes(), QueryThreadCycleTime() και QueryProcessCycleTime() αλλά

ας μην επεκταθούμε σ' αυτό.

 

Τα παραπάνω βέβαια είναι Windows specific.

Στην κονσόλα δεν έχω κοιτάξει αν υπάρχουν αντίστοιχες εντολές - όποιος ειδήμων ξέρει ας μας πει...

 

-

Δημοσ.

Αντίθετα, οι παραπάνω βασίζονται στον λεγόμενο 64-bit Time Stamp Counter (TSC) του επεξεργαστή

που μετρά το πλήθος των κύκλων από την στιγμή της εκκίνησης του υπολογιστή.

 

Αν υπολογιστης ειναι ανοικτος για μερες θα βγαλει overflow;

Παιζει και σε επεξεργαστη 32-bit;

 

Ψαχνοντας στο internet ειχα βρει καπου να λενε οτι για να επιτυχουμε κινηση ενος sprite με την ιδια ταχυτητα σε καθε υπολογιστη (αργο ή γρηγορο) θα πρεπει να χρησιμοποιηθουν οι συναρτησεις QueryPerformanceFrequency & QueryPerformanceCounter. Αυτο που δεν μπορω να βρω ειναι καποιον αλγοριθμο ο οποιος κανει αυτη τη δουλεια.

Δημοσ.

Αν υπολογιστης ειναι ανοικτος για μερες θα βγαλει overflow;

Παιζει και σε επεξεργαστη 32-bit;

Ναι, παίζει και σε 32 bit.

Δεν βγάζει overflow. Νομίζω ότι ο μετρητής απλώς μηδενίζεται και ξαναρχίζει απ' την αρχή.

Η μέγιστη τιμή όμως είναι τόσο μεγάλη (2^64 = 18446744073709551616) που αυτό πρακτικά δεν συμβαίνει πριν περάσουν μέρες.

Τα απλά χρονόμετρα των Windows που τίθενται με τις SetTimer, KillTimer και TimerProc έχουν ακρίβεια 10-15 ms και χρησιμοποιούν 32 bit τιμές.

Θεωρητικά μπορούν να μετρήσουν απο 1 έως 2^32 = 4,294,967,295 msec, δηλ. διάστημα περίπου 50 ημερών.

Αν βέβαια θέλεις να μετρήσεις κάτι πιο σύντομο από 10 ms δεν θα το δουν. Το λειτουργικό δεν μπορεί να πιάσει μυνήματα σε πιο λίγο χρόνο από αυτόν.

Σε αυτά τα πλαίσια είναι και η clock().

Η QueryPerformanceCounter() έχει ακρίβεια γύρω στο ns, δηλ. 1000 φορές μεγαλύτερη. Αλλά δουλεύει μετρώντας κτύπους ρολογιού, όχι sec.

 

 

Ψαχνοντας στο internet ειχα βρει καπου να λενε οτι για να επιτυχουμε κινηση ενος sprite με την ιδια ταχυτητα σε καθε υπολογιστη (αργο ή γρηγορο)

θα πρεπει να χρησιμοποιηθουν οι συναρτησεις QueryPerformanceFrequency & QueryPerformanceCounter.

Αυτο που δεν μπορω να βρω ειναι καποιον αλγοριθμο ο οποιος κανει αυτη τη δουλεια.

 

Εύκολο είναι.

Έστω ότι θέλεις να κινείς το sprite π.χ. ανά t sec.

Είπαμε ότι η QueryPerformanceFrequency() δίνει τους κτύπους/sec, έστω k, που έχει κάθε επεξεργαστής.

Σε t sec γίνονται t*k κτύποι.

Άρα καλείς την ρουτίνα κίνησης κάθε t*k κτύπους που αντιστοιχούν σε t sec σε οποιοδήποτε μηχάνημα.

 

-

Δημοσ.

Η μέγιστη τιμή όμως είναι τόσο μεγάλη (2^64 = 18446744073709551616) που αυτό πρακτικά δεν συμβαίνει πριν περάσουν μέρες.

 

Στο μελλον ισως να ειναι και ωρες εφοσον η επεξεργαστικη ισχυ ανεβει πολυ και η λυση θα ειναι τα 128-bit φανταζομαι.

 

 

Εύκολο είναι.

Έστω ότι θέλεις να κινείς το sprite π.χ. ανά t sec.

Είπαμε ότι η QueryPerformanceFrequency() δίνει τους κτύπους/sec, έστω k, που έχει κάθε επεξεργαστής.

Σε t sec γίνονται t*k κτύποι.

Άρα καλείς την ρουτίνα κίνησης κάθε t*k κτύπους που αντιστοιχούν σε t sec σε οποιοδήποτε μηχάνημα.

 

Αν θελω να κινω ενα sprite καθε t δευτερολεπτα μπορω να κανω χρηση ενα timer control και να το ορισω καθε t δευτερολεπτα να μετακινει το sprite. Δεν ζηταω αυτο ομως. Αυτο που ζηταω ειναι να κανω μια παυση πολυ μικρη κατω απο 0.1 ή 0.01 sec ωστε το sprite να κινειται με μια γρηγορη ταχυτητα η οποια θα ειναι ιδια σε καθε υπλογιστη. Αν δεν βαλω αυτη την παυση το sprite θα κινειται οσο πιο γρηγορα γινεται (δεν θα προλαβαινω να το βλεπω) αναλογα με την ταχυτητα του καθε υπολογιστη. Πως θα χρησιμοποιησω την QueryPerformanceCounter και την QueryPerformanceFrequency για να το πετυχω;

Δημοσ.

Κατάλαβα τι λες.

Να πώς θα το κάνεις.

 

Η υλοποίηση κίνησης πρέπει να γίνεται μέσω μιας εξίσωσης της μορφής s = f(υ,t) .

Αναβαθμίζεις τον χρόνο t κατά dt και βρίσκεις την θέση (κίνηση) με βάση αυτόν,

άρα και το πού τίθεται στην οθόνη.

Στην πραγματικότητα κάνεις προσομοίωση κίνησης.

 

Σε περιπτώσεις όπου χρειάζεται κίνηση ανά συγκεκριμένο χρονικό διάστημα Δt,

μπορείς να κάνεις την αναβάθμιση του χρόνου της εξίσωσης (άρα και της θέσης στην οθόνη) μετρώντας με

χρονόμετρο (κοινό ή ακριβείας) αν έχει παρέλθει αληθινός χρόνος Δt.

Συνήθως τα frameworks για παιχνίδια έτσι το κάνουν.

Η ρουτίνα κίνησης είναι καλύτερο να καλείται στον βρόγχο μυνημάτων μόλις έρθει η σειρά της,

δηλ. όσο πιο συχνά αντέχει ο υπολογιστής - πυκνότερα και από .01 s αν είναι αρκετά γρήγορος.

(Αντίθετα, η SetTimer δεν μπορεί να στείλει μυνήματα τόσο πυκνά.)

Επειδή έτσι θα υπάρχει το πρόβλημα που είπες, για να έχεις σταθερή ταχύτητα κίνησης σε κάθε υπολογιστή,

ελέγχεις αν έχει παρέλθει χρόνος π.χ. delay_time από την τελευταία κλήση της κίνησης και μόνον τότε

αναβαθμίζεις τον χρόνο κίνησης για να κουνηθεί το sprite.

 

Να ένα απόσπασμα απο dοκιμές μου στο DX9. Έστω ότι κινείς ένα σκάφος το οποίο πυροβολεί.

Δες τα παρακάτω, είναι η απάντηση σε αυτό που ρωτάς.

 

 

Bρόγχος μυνημάτων :

Το dt κρατά κάθε φορά τον χρόνο μεταξύ διαδοχικών κλήσεων της updateScene() που ανανεώνει την σκηνή.

Για να υπολογιστεί το dt με ακρίβεια, εφαρμόζονται οι QueryPerformanceCounter() και QueryPerformanceFrequency().

>int D3DApp::run()
{
MSG  msg;
            msg.message = WM_NULL;

__int64 cntsPerSec = 0;
QueryPerformanceFrequency((LARGE_INTEGER*)&cntsPerSec);
float secsPerCnt = 1.0f / (float)cntsPerSec;

__int64 prevTimeStamp = 0;
QueryPerformanceCounter((LARGE_INTEGER*)&prevTimeStamp);

while(msg.message != WM_QUIT)
{
	// If there are Window messages then process them.
	if(PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
	{
                             TranslateMessage( &msg );
                             DispatchMessage( &msg );
	}
	// Otherwise, do animation/game stuff.
	else
       {	
		if( !isDeviceLost() )
		{
			__int64 currTimeStamp = 0;
			QueryPerformanceCounter((LARGE_INTEGER*)&currTimeStamp);
			float dt = (currTimeStamp - prevTimeStamp)*secsPerCnt;

			updateScene(dt);
			drawScene();

			// Prepare for next iteration: The current time stamp becomes
			// the previous time stamp for the next iteration.
			prevTimeStamp = currTimeStamp;
		}
       }
   }
return (int)msg.wParam;
}

 

Το dt χρησιμοποιείται για να αναβαθμίσει την θέση του σκάφους και των σφαιρών στις updateShip και updateBullets.

Οι συναρτήσεις αυτές χειρίζονται τα sprites και καλούνται εντός της updateScene().

Η updateScene() καλεί συναρτήσεις κίνησης, αναβαθμίζει μεταβλητές κλπ :

>void SpriteDemo::updateScene(float dt)
{
     mGfxStats->setTriCount(4 + mBulletList.size()*2);
     mGfxStats->setVertexCount(8 + mBulletList.size()*4);

     // Get snapshot of input devices.
     gDInput->poll();

     // Update game objects.
     updateShip(dt);
     updateBullets(dt);
}

 

To σκάφος μετακινείται σύμφωνα με τις εξισώσεις κίνησης v= γ t και s = υ t.

>void SpriteDemo::updateShip(float dt)
{
     // Check input.
     if( gDInput->keyDown(DIK_A) ) mShipRotation += 4.0f * dt;
     if( gDInput->keyDown(DIK_D) ) mShipRotation -= 4.0f * dt;
     if( gDInput->keyDown(DIK_W) ) mShipSpeed    += SHIP_ACCEL * dt;
     if( gDInput->keyDown(DIK_S) ) mShipSpeed    -= SHIP_ACCEL * dt;

     // Clamp top speed.
     if( mShipSpeed > MAX_SHIP_SPEED )
         mShipSpeed = MAX SHIP SPEED;
     if( mShipSpeed < -MAX_SHIP_SPEED )
         mShipSpeed = -MAX SHIP SPEED;

     // Rotate counterclockwise when looking down -z axis,
     // rotate clockwise when looking down the +z axis.
     D3DXVECTOR3 shipDir(-sinf(mShipRotation),
                         cosf(mShipRotation), 0.0f);

     // Update position and speed based on time.
     mShipPos   += shipDir * mShipSpeed * dt;
     mShipSpeed -= SHIP_DRAG * mShipSpeed * dt;
}

 

Η updateBullets(dt) είναι για να πυροβολείς.

Ήθελα οι πυροβολισμοί να μην γίνονται συντομότερα απο κάθε 0.1 sec, οπότε έβαλα την παύση που είπες :

Η μεταβλητή fireDelay κρατά τον χρόνο μεταξύ πυροβολισμών προσθέτοντας το διάστημα dt διαδοχικών κλήσεων.

Ελέγχω αν έχει παρέλθει 0.1 sec και μόνον τότε αναβαθμίζω. Είναι αυτό ακριβώς που ρώτησες.

 

>void SpriteDemo::updateBullets(float dt)
{
     // Make static so that its value persists across function calls.
        static float fireDelay = 0.0f;

     // Accumulate time.
       fireDelay += dt;

//  αποφυγή πολύ γρήγορης κίνησης
     /*  Did the user press the Spacebar key and has 0.1 seconds
         passed? We can only fire one bullet every 0.1 seconds.
         If we do not put this delay in, the ship will fire
         bullets way too fast. */
         if( gDInput->keyDown(DIK_SPACE) && fireDelay > 0.1f )
     {
           BulletInfo bullet;

           // Remember, the ship is always drawn at the center of
           // the window--the origin. Therefore, bullets originate
           // from the origin (i.e., from the ship).
           bullet.pos      = D3DXVECTOR3(0.0f, 0.0f, 0.0f);

           // The bullet's rotation should match the ship's rotating
           // at the instant it is fired.
           bullet.rotation = mShipRotation;

           // Bullet just born.
           bullet.life     = 0.0f;

           // Add the bullet to the list.
           mBulletList.push_back(bullet);

           // A bullet was just fired, so reset the fire delay.
           fireDelay = 0.0f;
     }
     // Now loop through each bullet, and update its position.
     std::list<BulletInfo>::iterator i = mBulletList.begin();
     while( i != mBulletList.end() )
     {
           // Accumulate the time the bullet has lived.
           i->life += dt;

           // If the bullet has lived for two seconds, delete it.
           // By now the bullet should have flown off the
           // screen and cannot be seen.
           if(i->life >= 2.0f)
                 i = mBulletList.erase(i);

           // Otherwise, update its position by moving along
           // its directional path. Code similar to how we move
           // the ship.
           else
           {
                 D3DXVECTOR3 dir(-sinf(i->rotation), cosf(i->rotation), 0.0f);
                 i->pos += dir * BULLET_SPEED * dt;
                 ++i;
           }
     }
}

 

 

Όπως βλέπεις oi QueryPerformanceCounter() και QueryPerformanceFrequency(), είναι απλώς μετρητές ακριβείας και

χρησιμοποιούνται για να βρεθεί με ακρίβεια το dt μεταξύ των κλήσεων.

Δεν στέλνουν μύνημα για να κάνει το λειτουργικό κάτι όπως θα έστελνε η SetTimer.

Το dt μεταξύ των frames (κλήσεις της updateScence) μπορεί να διαφέρει μεταξύ των υπολογιστών αλλά

στην ρουτίνα κίνησης (εδώ στους πυροβολισμούς) ελέγχεται αν έχει παρέλθει ο επιθυμητός χρόνος και τότε μόνον αναβαθμίζεται (εδώ πυροβολεί).

 

 

Όλες οι παραπάνω εντολές για τις οποίες μιλήσαμε είναι σύγχρονες και αν δεν επιστρέψουν γρήγορα θα καθυστερήσουν

την επεξεργασία των υπολοίπων στην ουρά.

Ένας τρόπος για να αποφευχθεί αυτό είναι με νήματα.

Αυτά δουλεύουν ασύγχρονα και σε πολύ μικρά διαστήματα (μικρότερα πάντως από αυτά των WM_TIMER μυνημάτων).

Αν κάποιος έχει δοκιμάσει ας μας πει...

 

-

Δημοσ.

smirnov Η peek μπαινει σε while γιατι μπορει να εχει πολλα μηνυματα στη σειρα.

geo Πρινα ξετιναξεις τα FPS εχε στο νου σου οτι η οθονες ειναι στα 60Hz (100hz οι gamers) δλδ δεν εχει νοημα να δωσεις 100 frames σε μια οθονη που περνει 60.

ΥΓ: Εαν κανεις debugging και απορεις γιατι εχεις κολλησει στα 60 ή 75 ή 100 fps τοτε απενεργοποιησε το VSync

Δημοσ.

smirnov Η peek μπαινει σε while γιατι μπορει να εχει πολλα μηνυματα στη σειρα.

Aκριβώς αυτό έχω κάνει : το rendering της σκηνής γίνεται μόνον αν δεν υπάρχουν μυνήματα προς επεξεργασία.

 

Πριν να ξετιναξεις τα FPS εχε στο νου σου οτι η οθονες ειναι στα 60Hz (100hz οι gamers) δλδ δεν εχει νοημα να δωσεις 100 frames σε μια οθονη που περνει 60.

ΥΓ: Εαν κανεις debugging και απορεις γιατι εχεις κολλησει στα 60 ή 75 ή 100 fps τοτε απενεργοποιησε το VSync

 

Σωστό αυτό που λες. Αλλά εγώ έχω παλιό μηχάνημα και δεν με έχει προβληματίσει αυτό.

Συνήθως έβαζα έναν μετρητή που έδειχνε πόσα FPS κάνει ο υπολογιστής - ήταν πάντα κάτω από 60.

Δηλ. αν η οθόνη πιάνει π.χ. μόνον 60, κρατάει και το πρόγραμμα εκεί ;

ή το πρόγραμμα μπορεί να ρίχνει και να μετράει περισσότερα FPS αλλά χωρίς να τα βλέπεις ;

 

 

 

@dop

 

H GetTickCount() (όπως και η GetThreadTimes() που αναφέρεται σε νήμα) έχει ακρίβεια όπως η clock(), δηλ. χαμηλή.

Για ακριβές profilling, η QueryPerformanceCounter() είναι μονόδρομος - απ' όσο ξέρω τουλάχιστον...

 

-

Δημοσ.

Aκριβώς αυτό έχω κάνει : το rendering της σκηνής γίνεται μόνον αν δεν υπάρχουν μυνήματα προς επεξεργασία.

 

 

 

Σωστό αυτό που λες. Αλλά εγώ έχω παλιό μηχάνημα και δεν με έχει προβληματίσει αυτό.

Συνήθως έβαζα έναν μετρητή που έδειχνε πόσα FPS κάνει ο υπολογιστής - ήταν πάντα κάτω από 60.

Δηλ. αν η οθόνη πιάνει π.χ. μόνον 60, κρατάει και το πρόγραμμα εκεί ;

ή το πρόγραμμα μπορεί να ρίχνει και να μετράει περισσότερα FPS αλλά χωρίς να τα βλέπεις ;

 

 

 

-

 

Αν ειναι enabled το vsycn δε μπορεις να πας πανω απο τα hz της οθονης. Αν δεν ειναι μπορεις, αλλα ποιος ο λογος;

 

Btw εξαρτατε απο δυο πραγματα

1) Τις ρυθμισεις της καρτας

2) τις ρυθμισεις του δ3δ (βλ PresentationIntervals)

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...