Zwei TLB-miss pro mmap / access / munmap

8
%Vor%

Ich erwarte ~ 100000 dTLB-Speicherfehler im Userspace, einen pro Iteration (auch ~ 100000 Seitenfehler und dTLB-Ladefehler für den Kernel). Wenn Sie den folgenden Befehl ausführen, ist das Ergebnis ungefähr das Doppelte, was ich erwarte. Ich würde mich freuen, wenn jemand klären könnte, warum das der Fall ist:

%Vor%

P.S. Ich habe überprüft und bin sicher, dass der generierte Code nichts bringt, was dieses Ergebnis rechtfertigen würde. Außerdem bekomme ich ~ 100000 Seitenfehler und dTLB-Ladefehler: k.

    
Hedy 31.01.2018, 22:16
quelle

2 Antworten

6
  

Ich erwarte ~ 100000 dTLB-Speicherfehler im Userspace, einen pro Iteration

Ich würde das erwarten:

  • CPU versucht page[0] = 0; zu laden, versucht die Cachezeile zu laden, die page[0] enthält, kann den TLB-Eintrag nicht finden, erhöht dTLB-load-misses , holt die Übersetzung, erkennt, dass die Seite "nicht vorhanden" ist, erzeugt dann einen Seitenfehler.
  • Der Seitenfehlerhandler weist eine Seite zu und stellt (da die Seitentabelle geändert wurde) sicher, dass der TLB-Eintrag ungültig wird (möglicherweise aufgrund der Tatsache, dass Intel-CPUs die nicht vorhandenen Seiten sowieso nicht unbedingt explizit cachen) macht INVLPG ). Der Seitenfehlerhandler kehrt zu dem Befehl zurück, der den Fehler verursacht hat, so dass er erneut versucht werden kann.
  • CPU versucht page[0] = 0; ein zweites Mal auszuführen, versucht die Cachezeile zu laden, die page[0] enthält, kann den TLB-Eintrag nicht finden, erhöht dTLB-load-misses , holt die Übersetzung und ändert dann die Cachezeile.

Zum Spaß könnten Sie das MAP_POPULATE -Flag mit mmap() verwenden, um zu versuchen, den Kernel dazu zu bringen, die Seiten vorher zuzuweisen (und den Seitenfehler und den ersten TLB-Fehler zu vermeiden).

    
Brendan 01.02.2018, 07:14
quelle
3

Update 2 : Ich denke, Brendans Antwort ist richtig. Ich sollte das vielleicht löschen, aber der ocperf.py Vorschlag ist immer noch nützlich für zukünftige Leser, denke ich. Und es könnte zusätzliche TLB-Misses auf CPUs ohne Process-Context-Identifiers mit Kernels erklären, die Meltdown abschwächen.

Update : Die unten stehende Schätzung war falsch. Neue Vermutung: mmap muss die Seitentabelle Ihres Prozesses ändern, also gibt es vielleicht eine TLB-Invalidierung von etwas gerade daraus. Meine Empfehlung, ocperf.py record zu verwenden, um herauszufinden, welche asm-Anweisungen TLB-Misses verursachen, steht immer noch. Selbst wenn die Optimierung aktiviert ist, wird der Code auf dem Stapel gespeichert, wenn eine Rücksprungadresse für die Glibc-Wrapperfunktionsaufrufe gedrückt wird.

Vielleicht hat Ihr Kernel eine Kernel / User-Page-Table-Isolation aktiviert, um Meltdown abzuschwächen , also bei der Rückkehr vom Kernel Für den Benutzer wurden alle TLB-Einträge ungültig gemacht (indem CR3 geändert wurde, um auf Seitentabellen zu zeigen, die die Kernelzuordnungen überhaupt nicht enthalten).

Suchen Sie in Ihrer dmesg-Ausgabe nach Kernel/User page tables isolation: enabled . Sie können versuchen, mit kpti=off als Kerneloption zu booten, um sie zu deaktivieren, wenn es Ihnen nichts ausmacht, während des Tests anfällig für Meltdown zu sein.

Da Sie C verwenden, verwenden Sie die Systemaufrufe mmap und munmap über ihre Glibc-Wrapper, nicht direkt über die Inline-Anweisungen syscall . Der Befehl ret in diesem Wrapper muss die Rücksprungadresse vom Stapel laden, die der TLB nicht enthält.

Die zusätzlichen Speicherfehler kommen wahrscheinlich von call Anweisungen, die eine Rücksprungadresse drücken, obwohl ich mir nicht sicher bin, dass die aktuelle Stapelseite bereits im TLB von ret vom vorherigen Systemaufruf sein sollte.

Sie können Profile mit ocperf.py erstellen, um symbolische Namen für bestimmte Ereignisse zu erhalten. Angenommen, Sie befinden sich auf einer aktuellen Intel-CPU, ocperf.py record -e mem_inst_retired.stlb_miss_stores,page-faults,dTLB-load-misses , um zu ermitteln, welche Anweisungen Speicherfehler verursachen. (Verwenden Sie dann ocperf.py report -Mintel ). Wenn report es nicht einfach macht zu wählen, für welches Ereignis es zählt, nehmen Sie nur mit einem einzelnen Ereignis auf.

mem_inst_retired.stlb_miss_stores ist ein "präzises" Ereignis, im Gegensatz zu den meisten anderen TLB-Speicherereignissen, also sollten die Zählungen für die echte Anweisung und nicht für spätere Anweisungen wie ungenaue Perf-Ereignisse gelten. (Siehe Andy Glews Trap vs. Exception-Antwort für einige Details darüber, warum einige Leistungsindikatoren nicht leicht präzise sein können, viele Speicherereignisse nicht.

Peter Cordes 31.01.2018 23:43
quelle