CPUID wird serialisiert, wodurch die Ausführung von RDTSC außerhalb der Reihenfolge verhindert wird.
Heutzutage können Sie stattdessen sicher LFENCE verwenden. Es ist dokumentiert als Serialisierung auf dem Befehlsstrom (aber nicht speichert in den Speicher) auf Intel-CPUs, und jetzt auch auf AMD nach ihrer Microcode-Update für Spectre.
https://hadibrais.wordpress.com/2018/05/14/the-significance-of-the-x86-lfence-instruction/ erklärt mehr über LFENCE.
Siehe auch https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/ia-32-ia-64-benchmark-code-execution-paper.pdf für eine Möglichkeit, RDTSC zu verwenden P die CPUID (oder LFENCE) aus dem zeitlich begrenzten Bereich heraushält:
LFENCE ; (or CPUID) Don't start the timed region until everything above has executed
RDTSC ; EDX:EAX = timestamp
mov ebx, eax ; low 32 bits of start time
code under test
RDTSCP ; built-in one way barrier stops it from running early
LFENCE ; (or CPUID) still use a barrier after to prevent anything weird
sub eax, ebx ; low 32 bits of end-start
Siehe auch CPU-Zykluszahl abrufen? für weitere Informationen über RDTSC-Caveats, wie constant_tsc und nonstop_tsc.
Als Bonus erhalten Sie mit RDTSCP eine Kern-ID. Sie könnten RDTSCP auch für die Startzeit verwenden, wenn Sie die Kernmigration überprüfen wollen. Aber wenn Ihre CPU die constant_tsc
Features sollten alle Kerne im Paket ihre TSCs synchronisiert haben, so dass Sie dies auf modernen x86-Systemen normalerweise nicht benötigen.
Sie können die Kern-ID stattdessen von CPUID abrufen, wie in der Antwort von @Tony dargelegt.