Wie kann ich feststellen, ob jeder Kern meines Rechners den gleichen Timer verwendet?

8

Ich versuche, Code zu schreiben, um festzustellen, ob clock_gettime mit CLOCK_MONOTONIC_RAW benutzt wird, um Ergebnisse zu erhalten, die von derselben Hardware auf verschiedenen Kernen kommen.

Nach meinem Verständnis ist es für jeden Kern möglich, unabhängige Ergebnisse zu erstellen, aber nicht immer . Ich hatte die Aufgabe, Timings auf allen Kernen mit einer Genauigkeit von 40 Nanosekunden zu erhalten.

Der Grund, warum ich CLOCK_REALTIME nicht verwende, ist, dass mein Programm absolut nicht von NTP-Anpassungen betroffen sein darf.

Bearbeiten:

Ich habe die Funktion unsynchronized_tsc gefunden, die versucht Testen Sie, ob der TSC auf allen Kernen gleich ist. Ich versuche nun herauszufinden, ob CLOCK_MONOTONIC_RAW auf dem TSC basiert.

Letzte Änderung :

Es stellt sich heraus, dass CLOCK_MONOTONIC_RAW immer auf Multicore-Systemen verwendbar ist und nicht auf TSC angewiesen ist, nicht einmal auf Intel-Maschinen.

    
OlivierLi 24.03.2014, 15:22
quelle

1 Antwort

4

Um Messungen genau zu machen; Du brauchst:

  • Code, der auf allen CPUs ausgeführt wird, der den Zeitstempel-Zähler der CPU liest und speichert, sobald "ein Ereignis eintritt"
  • eine Möglichkeit, ein Ereignis zu erstellen, das von allen CPUs gleichzeitig bemerkt wird
  • eine Möglichkeit, Timing-Probleme zu vermeiden, die durch IRQs, Task-Switches usw. verursacht werden.

Verschiedene Möglichkeiten für das Ereignis umfassen:

  • Abfrage eines Speicherorts in einer Schleife, wobei eine CPU einen neuen Wert schreibt und andere CPUs die Abfrage abbrechen, wenn sie den neuen Wert sehen
  • Verwenden Sie den lokalen APIC, um eine IPI (interprozessor interrupt) an alle CPUs
  • zu senden

Für diese beiden Methoden gibt es Verzögerungen zwischen den CPUs (besonders bei größeren NUMA-Systemen) - ein Schreiben in den Speicher (Cache) kann auf der CPU sichtbar sein, die den Schreibvorgang sofort ausführt und von einer CPU auf einem anderen sichtbar ist Physischer Chip (in einer anderen NUMA-Domäne) später. Um dies zu vermeiden, müssen Sie möglicherweise den Durchschnitt der Initiierung des Ereignisses auf allen CPUs finden. Z.B. (für 2 CPUs) eine CPU initiiert und beide messen, dann initiiert die andere CPU und beide messen, dann werden die Ergebnisse kombiniert, um jegliche "Ereignisausbreitungslatenz" aufzuheben.

Um andere Timing-Probleme (IRQs, Task-Switches usw.) zu beheben, möchte ich diese Tests während des Bootens durchführen, wo nichts anderes die Dinge durcheinander bringen kann. Andernfalls müssen Sie entweder die Probleme verhindern (sicherstellen, dass alle CPUs mit der gleichen Geschwindigkeit laufen, IRQs deaktivieren, Thread-Schalter deaktivieren, PCI-Bus-Mastering beenden usw.) oder Probleme bewältigen (z. B. denselben Test mehrmals ausführen und prüfen, ob Sie erhalten die meiste Zeit ähnliche Ergebnisse).

Beachten Sie auch, dass all diese Punkte nur gewährleisten können, dass die Zeitstempel-Zähler zum Zeitpunkt des Tests synchronisiert waren und nicht garantieren, dass sie nach Abschluss des Tests nicht mehr synchron sind. Um sicherzustellen, dass die CPUs synchron bleiben, müssen Sie sich auf die "monotonic clock" -Garantie der CPU verlassen (aber ältere CPUs geben diese Garantie nicht ab).

Schließlich; wenn Sie dies im User-Space versuchen (und nicht im Kernel-Code); Dann rate ich, Code so zu gestalten, dass er zunächst nicht so fragil ist. Selbst wenn die TSCs auf verschiedenen CPUs garantiert immer perfekt synchronisiert sind, können Sie nicht verhindern, dass ein IRQ unmittelbar vor oder unmittelbar nach dem Lesen des TSC unterbrochen wird (und es gibt keine Möglichkeit, atomar etwas zu tun und TSC gleichzeitig zu lesen Zeit); Wenn Ihr Code ein genau synchronisiertes Timing erfordert, ist das Design Ihres Codes wahrscheinlich fehlerhaft.

    
Brendan 24.03.2014, 16:21
quelle

Tags und Links