C++ PerformanceCounter liefert mir immer einen anderen Wert zurück

azdr

Lieutenant
Registriert
Feb. 2005
Beiträge
685
Mein Problem ist folgendes immer wenn ich eine Zeitmessung durchführe bekomme ich jedesmal einen anderen Wert raus.

z.b.: Bekomme ich bei jedem Durchgang für die gleiche Bildberechnung:
0,1689s
0,1623s
0,1540s
0,1715s

Liegts daran das der Performancecounter ungenau ist oder liegts am Code?
lg

Code:
#include <iostream>
#include <stdio.h>
#include <Windows.h>

LARGE_INTEGER anfang  , ende, freq;



double CPU_CANNY()
{

   QueryPerformanceCounter(&anfang);

         // CODE FÜR BILDVERARBEITUNG

   QueryPerformanceCounter(&ende);

   double ZeitMessungCPU = (double)(ende.QuadPart - anfang.QuadPart) / (double)freq.QuadPart;
   return ZeitMessungCPU;

}

int main(int argc, char *argv[])
{
     double time_cpu = 0;

     if (QueryPerformanceFrequency(&freq) == 0) cout << "\nPerformance Counter nicht vorhanden\n";

     time_cpu = CPU_CANNY();
     cout<<time_cpu<<endl;

system("Pause");
}
 
Zuletzt bearbeitet:
Der CPU ist ja nicht nur für dein Programm da... der macht noch andere Dinge im Hintergrund, deswegen kanns auch unterschiedlich lang dauern.
 
Davon ausgehend, das IMMER die gleiche Zeit benötigt wird: Stell die CPU-Frequenz auf einen festen Wert ein. Ich vermute mal, das die heruntertaktet, auf Anfrage hochtaktet und daher immer minimaler Unterschied im Ergebnis besteht.
 
Vielleicht hilft es, den Prozess auf die höchste Prioritätsstufe zu setzen, damit das OS ihn garnicht bis kaum unterbricht.
 
firexs schrieb:
Davon ausgehend, das IMMER die gleiche Zeit benötigt wird: Stell die CPU-Frequenz auf einen festen Wert ein. Ich vermute mal, das die heruntertaktet, auf Anfrage hochtaktet und daher immer minimaler Unterschied im Ergebnis besteht.

Naja das Programm soll auf verschiedenen Rechnern getestet werden da kann ich schlecht an der Taktfreq. von fremden Rechnern rumfummeln.
 
Das ist vollkommen normal und hängt mit dem Prozess Scheduler des Betriebssystems zusammen. Wie thechain ja auch schon angemerkt hat, laufen auf der CPU i.d.R. ja mehrere dutzend Prozesse die alle mal mehr und mal weniger CPU-Zeit zugewiesen bekommen.
Das Ergebnis solltest du eher als grobe Richtgröße sehen für die Performance Optimierung daher nur bedingt geeignet. Man sollte daher die Messung möglichst oft durchführen und dann ggf. einen Mittelwert bilden.
 
Du brauchst mehr RAM und eine neue Grafikkarte. Eindeutig.
Nein Quatsch, Green Mamba und thecain treffen den Nagel auf den Kopf. Dazu kommt noch Messungenauigkeit. Da kannst Du nicht viel machen.
Ich sag mal so: wenn Du es durch Optimierung schaffst, den Zeitbetrag von 0,16 auf 0,06 zu drücken, dann hast Du definitiv was richtig gemacht. Über so kleine Fluktuationen brauchst Du Dir aber keine Gedanken zu machen.
 
Zuletzt bearbeitet:
Was man immer für genauere Werte machen kann: Mehrere Messungen. Einfach dieselbe Stelle Code mehrfach ausführen, und zwar so, dass auch das Verhalten bei den Aufrufen möglichst gleich bleibt (also ohne relevante Seiteneffekte).
 
VikingGe trifft es ganz gut. Normalerweise lässt man eine Performance-Messung in der Größenordnung von 10'000x laufen und bildet darüber dann den Durchschnitt. Dann bemerkst Du auch, wenn sich etwas verbessert hat.

Wenn Du das Benchmarking-Framework selbst schreibst, lohnt es sich vielleicht trotzdem, einen Blick darauf zu werfen, wie Profis das machen. Google hat beispielsweise eine sehr schicke Benchmarking-Library.
 
Kanibal schrieb:
VikingGe trifft es ganz gut. Normalerweise lässt man eine Performance-Messung in der Größenordnung von 10'000x laufen und bildet darüber dann den Durchschnitt. Dann bemerkst Du auch, wenn sich etwas verbessert hat.

vorher aber noch die schnellsten und langsamsten 10% der Ergebnisse abschneiden, dann ist das Ergebnis deutlich besser.
 
Es hat zwar nichts mit der Schwankung der Laufzeit zu tun, aber du solltest dir Zeile 18 und 27 noch einmal genauer anschauen. Besonders letzteres ist bedenklich. :)
 
ice-breaker schrieb:
vorher aber noch die schnellsten und langsamsten 10% der Ergebnisse abschneiden, dann ist das Ergebnis deutlich besser.

Ist das echt eine legitime Methode? Es klingt mir irgendwie seltsam, einfach 20% der Ergebnisse zu ignorieren.
 
antred schrieb:
Ist das echt eine legitime Methode? Es klingt mir irgendwie seltsam, einfach 20% der Ergebnisse zu ignorieren.
In manchen Fällen ist das durchaus angebracht. Wenn man in so einer Verteilung ein paar Ausreißer hat, die nichts mit der eigentlichen Messung zu tun haben sondern durch irgendwelche Fehler entstehen, weicht natürlich der Mittelwert ziemlich stark vom "eigentlichen Mittelwert" ab. Natürlich darf man bei sowas nicht zuviel der eigentlich "richtigen" Werte wegwerfen.
 
Ja das ist legitim, in der Statistik nennt sich das Percentile. Du schneidest eben von der Gauss-Glockenkurce links und rechts ein paar Prozent ab, denn das sin Außreser. Umso größere Mengen an Messungen du machst umso unwichtiger wird es, aber gerade bei kleineren Mengen möchtest du ja vermeiden, dass Außreiser jegliche Aussage verfälschen. Stell dir doch nur vor während dein Code läuft springt in einigen Durchläufen ein Prozess mit sehr hoher Priorität (Systemprocess) an, der gerade die gesammte Rechenleistung frisst: du wirdt einige Durchläufe mit wirklich katastrophalen Laufzeiten ab, was bedeutet dass dein Average immer schlechter wird.
 
Ja das mitm arithmetischen Mittelwert ist ne gute idee. Problematisch ist es halt wenn bei großen Bildgrößen zb. bei 50Megapixel eine einzelne Berechnung schon knapp 20Sekunden dauert wenn ich das 100x ausführe., kann ich lang warten.

@S.Kara was stimmt dem Code nicht ?
 
Dann kann man aber immer noch hergehen und sagen "rechne mal nicht länger als eine Minute", statt eine feste Anzahl von Runs laufen zu lassen.

Wobei bei 20s schon ein Lauf genügen dürfte, um ein gutes Ergebnis zu bekommen - vorausgesetzt natürlich, die Hintergrundlast ist minimal.
 
azdr schrieb:
@S.Kara was stimmt dem Code nicht ?
In Zeile 18 sind die Variable "ZeitMessungCPU" und das erste "(double) überflüssig.
In Zeile 27 fragst du ab ob die Hardware den Counter unterstützt, reagierst aber nicht auf das Ereignis.

Code:
double CPU_CANNY() {
	QueryPerformanceCounter(&anfang);
	
	// CODE FÜR BILDVERARBEITUNG
	
	QueryPerformanceCounter(&ende);
	
	return (ende.QuadPart - anfang.QuadPart) / (double)freq.QuadPart;
}
 
int main(int argc, char *argv[]) {
	if (QueryPerformanceFrequency(&freq) == 0) {
		cout << "\nPerformance Counter nicht vorhanden\n" << endl;
		return -1;
	}
	
	double time_cpu = CPU_CANNY();
	cout << time_cpu << endl;
	
	system("Pause");
}
 
S.Kara schrieb:
In Zeile 18 sind die Variable "ZeitMessungCPU" und das erste "(double) überflüssig.

Dann kannst du den Cast aber auch gleich noch auf static_cast umstellen. ;) Im Titel steht schließlich C++.

Und natürlich das stdio.h include auf cstdio ändern und immer schon den std::-Präfix verwenden.
 
ok danke für die Verbesserungen.



Was ich noch Fragen wollte ich habe ein Programm geschrieben bei welchem ich die rechenintensiven Berechnung (Kantendetektion) auf die Cores der GPU ausgelagert habe.

Nun wenn ich jetzt die Zeit messe so hab ich bei immer größer werdenden Bildern einen steigenden Speedup. Aber ab einer bestimmten Bildgröße bei ca. 40Megapixel fällt der SpeedUp der GPU gegeüber der CPU rapide steil ab also von 11x auf 3x so schnell.

Kann man das damit begründen das zudem Zeitpunkt alle Streamprozessoren der GPU schon beschäftigt sind und gewartet werden muss bis die parallelen Berechnungen fertig sind und somit zu einer Auslagerung von einem Teil der Berechnung kommt.

GPU: mit 1408 Streamprozessoren
 
Zuletzt bearbeitet:
Zurück
Oben