Funktion über Zeitspanne gleichverteilt aufrufen



  • Danke für die vielen Antworten.

    @imhotep: gettime() liefert mir die Zeit nur ms-genau, und wie du schon gesagt hast bin ich im ns-Bereich.

    @Volkard: wie sieht so eine Zeitschleife aus, kann mir nichts drunter vorstellen



  • #include <clock.h>
    
    int n=0,calls_per_second=20000;
    clock_t t;
    
    for(;;)
    {
      t=clock();
    
      n+=calls_per_second;
      while(n>=CLOCKS_PER_SEC)
      {
        funktion();
        n-=CLOCKS_PER_SEC;
      }
    
      while(clock()<=t);
    }
    

    braucht leider ein bißchen viel cpu-zeit. eine lösung mit Sleep() wäre ebenfalls möglich, aber ich muß jetzt in die heia :p



  • Danke Konfusius.
    Da ich aber so wenig CPU wie möglich verbrauchen will/muss hab ich folgendes ausprobiert

    HANDLE hTimer = NULL;
    LARGE_INTEGER liDueTime;
    
    QueryPerformanceFrequency( (LARGE_INTEGER*) &Frequency);
    hTimer = CreateWaitableTimer(NULL, TRUE, "WaitableTimer");
    
    int i=0;
    while(i<30000)
    {
    //Berechne Zeit für einen Funktionsaufruf
    QueryPerformanceCounter(&TU_Start);
    MyFunction();
    QueryPerformanceCounter(&TU_End);
    
    //Berechne Zeit die bis zum 1/500-tel Sekunde zu warten ist
    liDueTime.QuadPart =(long) -(((double)1/500 - (double)(TU_End.QuadPart-TU_Start.QuadPart)/(double)Frequency.QuadPart)*10000000);
    
    //Setze Timer		
    if (!SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, 0))
    {
    printf("SetWaitableTimer failed (%d)\n", GetLastError());
    return 2;
    }
    
    //Warte auf Timer
    if (WaitForSingleObject(hTimer, INFINITE) != WAIT_OBJECT_0)
    printf("WaitForSingleObject failed (%d)\n", GetLastError());
    
    i++;
    }
    

    Der Code funktioniert auch wunderbar, aber leider nur bis 100 Funktionsaufrufe/sec. Es ist egal ob ich 1/500 1/20000 schreib, der macht immer nur 1/100. woran könnte es liegen??



  • Dein Code:

    QueryPerformanceCounter(&TU_Start);
    MyFunction();
    QueryPerformanceCounter(&TU_End);
    

    Hat das Problem, dass wahrscheinlich immer eine Zeitdifferenz nahe 0 rauskommt.

    Die Granularitaet des Performance Counters kannst Du mittels QueryPerformanceFrequency() abfragen. Sie liegt z.B. bei ca. 600 kHz.

    Wenn Deine Funktion schneller ist, bekommst Du als Zeitdifferenz 0.

    Du musst also von der Granularitaet ausgehend, die Du mit QueryPerformanceFrequency() abgefragt hast, die Berechnung fuer die Zeitdauer eines Intervalls berechnen.

    Da bei Windows die tatsaechliche Granularitaet des Timings zwischen z.B. 600 kHz und 50 Hz liegt, also Dein Thread unter Umstaenden gar nicht rechtzeitig drankommt, wenn der Timer abgelaufen ist, kann der tatsaechliche Rhythmus Deiner Funktionsaufrufe stark schwanken.

    Aber probier's ruhig mal aus.



  • TU_End-TU_Start = 14
    FrequencyCounter = 3579545
    =>3,9111....*10hoch-6 also nicht 0 🙂

    Ich hab den Process schon mal mit realtime laufen lassen, kommt der gleiche Wert raus. Nie mehr als 100mal pro sekunde. Wenn ich das ganze ohne Timer durchlaufen lass, z.B. in einer Endlosschleife, erreiche ich Werte von bis zu 100000mal/sec, allerdings bei 100% CPU-Last. Ich möchte nun die Last reduzieren indem ich z.B. nur 20000mal/sec die Funktion aufrufe.



  • Vampy20 schrieb:

    Ich hab den Process schon mal mit realtime laufen lassen, kommt der gleiche Wert raus. Nie mehr als 100mal pro sekunde. Wenn ich das ganze ohne Timer durchlaufen lass, z.B. in einer Endlosschleife, erreiche ich Werte von bis zu 100000mal/sec, allerdings bei 100% CPU-Last. Ich möchte nun die Last reduzieren indem ich z.B. nur 20000mal/sec die Funktion aufrufe.

    Damit hast Du aber das Problem, dass Du nicht vorhersehen kannst, wie schnell Deine Funktion ueberhaupt ausgefuehrt wird, und ob dann z.B. 20000 mal ueberhaupt noch moeglich sind.

    Besser ist in dem Fall, Du gibst einfach den Rest Deiner Zeitscheibe ab:

    Sleep(0);  // Auf Ende der Zeitscheibe warten
    

    Damit sollte die CPU-Last etwas sinken.

    Du kannst natuerlich durch verschiedene Messungen feststellen, wie lange Deine Funktion im Durchschnitt braucht, und anhand dessen ausrechnen, wieviel Prozent der Rechenzeit Du beanspruchen willst und dann entsprechend lange warten.

    ULONGLONG GetCPUTicks( void ) {
       _asm {
          rdtsc
       }
    }
    
    ULONGLONG GetFuncTicks( void ) {
       ULONGLONG t0, t1, diff;
       t0 = GetCPUTicks();
       func(); // Deine Funktion
       t1 = GetCPUTicks();
       diff = ti1 - ti0;
       return diff;   
    }
    
    ULONGLONG GetFuncAverageTicks( void ) {
       // den Test z.B. 100 mal ausfuehren, um einen Mittelwert zu bekommen
       ULONGLONG sum = 0;
       for ( int i=0; i < 100; ++i ) {
          sum += GetFuncTicks();
       }
       return sum / 100U;
    }
    

    Von da aus auf einen Sleep()-Wert zu kommen, musste selber ausrechnen! 😉



  • bin wieder wach 😃

    hier nun eine getestete version, die kaum mehr cpu-zeit verbraucht:

    #include <windows.h>
    #include <iostream>
    
    using namespace std;
    
    void
    funktion ()
    {
      cout<<".";
    }
    
    int
    main ()
    {
      unsigned _int64	calls_per_hour=3600,
    					n=0,t,t_prev,dt;
      SYSTEMTIME		systime;
    
      GetSystemTime(&systime);
      SystemTimeToFileTime(&systime,reinterpret_cast<FILETIME*>(&t));
    
      for(;;)
      {
    	t_prev	= t;
    	GetSystemTime(&systime);
    	SystemTimeToFileTime(&systime,reinterpret_cast<FILETIME*>(&t));
    	dt		= (t-t_prev)/10000L; // time in milli-seconds
    
    	n+=dt*calls_per_hour;
    	while(n>=3600000L)
    	{
    	  funktion();
    	  n-=3600000L;
    	}
    
    	Sleep(3600000L/calls_per_hour);
      }
    
      return 0;
    }
    


  • hi, bin im programmiern noch blutiger anfänger un hab da jetzt n ähnliches problem, nur nicht ganz so kompliziert denk ich^^

    hier mein programm: einfaches würfelspiel was fragt ob gewürfelt werden soll, nach eingabe "j" wird gewürfelt mit 2 würfeln (random ausgabe). nebenbei soll ne zeitschleife laufen die alle 5minuten nachdem man wieder "j" zum würfeln eingegeben hat nen 3er pasch ausgibt.
    dachte da an sowas wie if(time-gepseichertertimestamp>300) mach paschausgabe else random nur mangelts mir an der umsetzung^^

    do
    {
    cout << "Wuerfeln? (j/n)";
    cin >> würfeln;
    if (würfeln == 'j')

    srand( time(NULL) );
    int w1 = rand() % 6 + 1;
    int w2 = rand() % 6 + 1;
    printf("Wuerfel 1: %d\nWuerfel 2: %d\n%s", w1, w2, (w1==w2) ? "Pasch!\n" : ""); } while (würfeln == 'j');

    so sieht das zur zeit aus, hoffe mir kann da jemand weiterhelfen 🙂



  • Warum verwendest du printf lieber std::cout

    srand( time(NULL) );
    do 
    {
    cout << "Wuerfeln? (j/n)"; 
    cin >> würfeln; 
    if (würfeln == 'j') 
    {
    int w1 = rand() % 6 + 1; 
    int w2 = rand() % 6 + 1;
    cout << "w1=" << w1 << " und w2=" << w2 << endl;
    if (w1 == w2)
    cout << "Pasch!" << endl;
    }
    }while (würfeln == 'j');
    


  • danke dafür schonmal^^ hatte mir den würfelcode aus nem forum geholt, deswegen hab ichs einfach so stehn lassen 🙂



  • wie kann ich denn die zeit überhaupt speichern. ich brauch ja erstmal die startzeit nachdem das erste mal gewürfelt wurde.



  • #include <iostream>
    #include <time.h>               // contains clock()
    
    using namespace std;
    
    int main()
    {
    	double time1=0.0, tstart;      // time measurment variables
    
    	//      read data 
    
    	tstart = clock();              // start 
    
    	//      some code
    
    	time1 += clock() - tstart;     // end
    	time1 = time1/CLOCKS_PER_SEC;  // rescale to seconds or "/ 1000"
    	cout << "  time = " << time1 << " sec." << endl;
    
    	return 0;
    }
    


  • hmm danke aber damit funktionierts irgendwie nich so wirklich 😞



  • willst du boost verwenden?

    #include <boost/thread.hpp>
    class delayer {
      boost::system_time last_delay;
      boost::time_duration delay_time;
    public:
      delayer(boost::time_duration delay) : last_delay(boost::get_system_time()), delay_time(delay) {}
      void delay() {
        last_delay = std::max(last_delay + delay_time, boost::get_system_time());
        boost::this_thread::sleep(last_delay);
      }
    };
    
    delayer d(boost::posix_time::microseconds(50));
    for (;;) {
      foo();
      d.delay(); // Wartet bis die 50 Millisekunden verstrichen sind
    }
    


  • Ups, ich habe auf die ursprüngliche Frage geantwortet.



  • Aber boost::thread::get_system_time() sollte schon einmal einen Tipp geben, wie man Zeit speichert.



  • zween schrieb:

    hmm danke aber damit funktionierts irgendwie nich so wirklich 😞

    Du musst schon Code zeigen was du machst, sonst kann dir nicht geholfen werden.



  • do{
    			cout << "Wuerfeln? (j/n)";
    			cin >> würfel;
    			if (würfel == 'j'){
    
    				srand( time(NULL) );
    gettime //zeitspeichern ka wie, if(time>5min) ausgabe w1=3 und w2=3, danach zeit resetten und neustart nach erneutem würfeln.
    				int w1 = rand() % 6 + 1;
    				int w2 = rand() % 6 + 1;
    				cout << "Wuerfel 1=" << w1 << endl <<"Wuerfel 2=" << w2 << endl;
    				if (w1 == w2)
    				cout << "Pasch!" << endl;   
    			}
    		}while(würfel == 'j');
    

    ums nochmal zu erklärn: nach dem ersten mal würfeln soll der timer gestartet werden der nach ablauf der 5min beim erneuten würfeln ein 3er pasch anstatt der random variante ausgibt. danach soll der timer resettet un neu gestartet werden.



  • #include <iostream> 
    #include <cstdio>
    #include <ctime>               // contains clock() 
    
    using namespace std; 
    
    int main() 
    { 
        double tstart;      // time measurment variables 
    	char würfeln;
    
    	tstart = clock();
    	srand( time(NULL) ); 
    
    	do 
    	{ 
    		cout << "Wuerfeln? (j/n)"; 
    		cin >> würfeln; 
    
    		if (würfeln == 'j') 
    		{ 
    			if (clock() - tstart < 5000)
    			{
    				int w1 = rand() % 6 + 1; 
    				int w2 = rand() % 6 + 1; 
    				cout << "w1=" << w1 << " und w2=" << w2 << endl; 
    				if (w1 == w2) 
    				cout << "Pasch!" << endl; 
    			}
    			else
    			{
    				cout << "w1=3 und w2=3" <<  endl;
    				cout << "Pasch dank schummeln!" << endl; 
    				tstart = clock();
    			}
    		}
    	}while (würfeln == 'j');
    
        return 0; 
    }
    

    Ist doch nicht so schwer das eine und das andere zusammenzubasteln?



  • aaaah super dank dir! ich hatte einfach n fehler drin. wie gesagt bin noch blutiger anfänger 😃


Anmelden zum Antworten