2009-02-22 13 views
8

Ich schreibe einige Mikro-Benchmark-Code für einige sehr kurze Operationen in C. Zum Beispiel, eine Sache, die ich messe, ist, wie viele Zyklen benötigt werden, um eine leere Funktion abhängig von der Anzahl der Argumente zu nennen.Die Befehlspipeline von Intel Core 2 Duo leeren?

Momentan verwende ich eine RDTSC-Anweisung vor und nach jeder Operation, um die Zyklusanzahl der CPU zu ermitteln. Ich bin jedoch besorgt, dass Anweisungen, die vor dem ersten RDTSC ausgegeben wurden, die tatsächlichen Anweisungen, die ich gerade vermesse, verlangsamen. Ich bin auch besorgt, dass die vollständige Operation möglicherweise nicht abgeschlossen ist, bevor das zweite RDTSC ausgegeben wird.

Kennt jemand eine x86-Anweisung, die alle In-Flight-Befehle zum Commit zwingt, bevor neue Befehle ausgegeben werden? Mir wurde gesagt, CPUID könnte dies tun, aber ich konnte keine Dokumentation finden, die das sagt.

Antwort

9

Nach meinem Wissen gibt es keine Anweisung, die die Pipeline spezifisch "entwässert". Dies kann leicht erreicht werden, wenn eine Serialisierungsanweisung verwendet wird.

CPUID ist eine Serialisierungsanweisung, die genau das bedeutet, wonach Sie suchen. Jeder Befehl tritt auf, bevor er vor dem CPUID-Befehl ausgeführt wird.

Also folgendes tun sollte die gewünschte Wirkung erhalten:

cpuid 
rdtsc 
# stuff 
cpuid 
rdtsc 

Aber, wie nebenbei bemerkt, empfehle ich nicht, dass Sie dies tun. Ihre "Sachen" können immer noch von vielen anderen Dingen außerhalb Ihrer Kontrolle beeinflusst werden (wie CPU-Caches, anderen Prozessen, die auf dem System laufen, usw.), und Sie werden nie in der Lage sein, sie alle zu beseitigen. Der beste Weg, um genaue Leistungsstatistiken zu erhalten, besteht darin, die Operation (en), die Sie mindestens mehrere Millionen Mal messen möchten, durchzuführen und die Ausführungszeit des Stapels zu mitteln.

Edit: Die meisten Befehlsreferenzen für CPUID werden seine Serialisierungseigenschaften wie die NASM manual appendix B erwähnen.

Bearbeiten 2: Vielleicht möchten Sie auch einen Blick auf this related question werfen.

+1

Sie haben Recht mit den Fence-Anweisungen. CPUID bedeutet sie tatsächlich (ich habe meine Antwort gelöscht). Beachten Sie, dass während der CPUID-Serialisierung die Caches nicht gelöscht werden, was sich ebenfalls auf die Leistung auswirken kann. Der Cache kann mit WBINVD gelöscht werden. Vielleicht möchten Sie das zu Ihrer Antwort hinzufügen. –

+0

wbinvd ist privilegiert ... Sie könnten jedoch clflush verwenden. Es gibt eine separate Frage über diese Art von Dingen aus der letzten Woche .... http://stackoverflow.com/questions/558848/can-i-force-cache-cohenerency-on-a-multicore-x86-cpu/558900# 558900 – SoapBox

+0

Große Antwort. Vielen Dank. –