Ich experimentiere mit den tsx-Erweiterungen in haswell, indem ich eine vorhandene mittelgroße (1000er Zeilen) Codebase an die Verwendung von GCC-Transaktionsspeichererweiterungen anpasst (die indirekt haswell tsx in dieser Maschine verwenden) statt grobkörniger Schlösser. Ich benutze die transactional_memory Erweiterungen von GCC und schreibe nicht meine eigene _xbegin/_xend direkt. Ich verwende die ITM_DEFAULT_METHOD = htmmysteriöse rtm abbrechen mit haswell tsx
Ich habe Probleme, es schnell genug zu arbeiten, weil ich hohe Raten von Hardware-Transaktion abbrechen aus mysteriösen Gründen. Wie unten gezeigt, sind diese Abbrüche nicht auf Konflikte oder Kapazitätsbeschränkungen zurückzuführen. Hier
ist der perf Befehl, den ich verwenden, um die Ausfallrate und die zugrunde liegende Ursachen zu quantifizieren:
perf stat \
-e cpu/event=0x54,umask=0x2,name=tx_mem_abort_capacity_write/ \
-e cpu/event=0x54,umask=0x1,name=tx_mem_abort_conflict/ \
-e cpu/event=0x5d,umask=0x1,name=tx_exec_misc1/ \
-e cpu/event=0x5d,umask=0x2,name=tx_exec_misc2/ \
-e cpu/event=0x5d,umask=0x4,name=tx_exec_misc3/ \
-e cpu/event=0x5d,umask=0x8,name=tx_exec_misc4/ \
-e cpu/event=0x5d,umask=0x10,name=tx_exec_misc5/ \
-e cpu/event=0xc9,umask=0x1,name=rtm_retired_start/ \
-e cpu/event=0xc9,umask=0x2,name=rtm_retired_commit/ \
-e cpu/event=0xc9,umask=0x4,name=rtm_retired_aborted/pp \
-e cpu/event=0xc9,umask=0x8,name=rtm_retired_aborted_misc1/ \
-e cpu/event=0xc9,umask=0x10,name=rtm_retired_aborted_misc2/ \
-e cpu/event=0xc9,umask=0x20,name=rtm_retired_aborted_misc3/ \
-e cpu/event=0xc9,umask=0x40,name=rtm_retired_aborted_misc4/ \
-e cpu/event=0xc9,umask=0x80,name=rtm_retired_aborted_misc5/ \
./myprogram -th 1 -reps 3000000
Also, das Programm einen Code läuft mit Transaktionen in es 30 Millionen mal. Jede Anfrage enthält eine Transaktion gcc __transaction_atomic
Block. Es gibt nur einen Thread in diesem Lauf.
Dieser spezielle Befehl perf
erfasst die meisten relevanten tsx-Leistungsereignisse, die in Intel software developers manual vol 3 beschrieben sind.
Die Ausgabe von perf stat
ist folgende:
0 tx_mem_abort_capacity_write [26.66%]
0 tx_mem_abort_conflict [26.65%]
29,937,894 tx_exec_misc1 [26.71%]
0 tx_exec_misc2 [26.74%]
0 tx_exec_misc3 [26.80%]
0 tx_exec_misc4 [26.92%]
0 tx_exec_misc5 [26.83%]
29,906,632 rtm_retired_start [26.79%]
0 rtm_retired_commit [26.70%]
29,985,423 rtm_retired_aborted [26.66%]
0 rtm_retired_aborted_misc1 [26.75%]
0 rtm_retired_aborted_misc2 [26.73%]
29,927,923 rtm_retired_aborted_misc3 [26.71%]
0 rtm_retired_aborted_misc4 [26.69%]
176 rtm_retired_aborted_misc5 [26.67%]
10.583607595 seconds time elapsed
Wie Sie aus der Ausgabe sehen:
- Die
rtm_retired_start
Zählung Millionen beträgt 30 (entspricht Eingang Programm) - Die
rtm_retired_abort
Die Anzahl ist ungefähr gleich (keine Commits) - Die
abort_conflict
undabort_capacity
zählt sind 0, also sind dies nicht die Gründe. Auch daran erinnern, es ist nur ein Thread läuft, Konflikte sollten selten sein. - Die einzigen tatsächlichen führt hier sind die hohen Werte von
tx_exec_misc1
undrtm_retired_aborted_misc3
, die in der Beschreibung etwas ähnlich sind.
Die Intel manual (Vol 3) definiert rtm_retired_aborted_misc3
Zähler:
Code: C9H 20H
Mnemonik: RTM_RETIRED.ABORTED_MISC3
Beschreibung: Anzahl der Male eines Die RTM-Ausführung wurde aufgrund von unfreundlichen HLE-Anweisungen abgebrochen.
Die Definition für tx_exec_misc1
hat einige ähnliche Wörter:
Code: 5DH 01H
mnemonic: TX_EXEC.MISC1
Beschreibung: Zählt die Häufigkeit, mit der eine Klasse von Anweisungen ausgeführt wurde, die einen Transaktionsabbruch verursachen konnten. Da dies die Anzahl der Ausführungen ist, kann es nicht immer zu einem Transaktionsabbruch kommen.
überprüfte ich die Montagestelle für die Abbrüche für rtm_retired_aborted
perf Aufnahme/perf Bericht mit hohen Präzision (PEBS)-Unterstützung. Der Ort hat eine mov
Anweisung aus dem Register zu registrieren. Keine seltsamen Instruktionsnamen in der Nähe.
Update:
Hier sind zwei Dinge, die ich seitdem versucht habe:
1) die tx_exec_misc1 und rtm_retired_aborted_misc3 Unterschrift wir uns hier sehen kann beispielsweise dadurch erhalten werden, durch einen Dummy-Block des Formulars
for (int i = 0; i < 10000000; i++){
__transaction_atomic{
_xabort(1);
}
}
oder einer Form
for (int i = 0; i < 10000000; i++){
__transaction_atomic{
printf("hello");
fflush(stdout);
}
}
In bo In den Fällen sehen die Perf-Zähler ähnlich aus wie ich es sehe. In beiden Fällen weist jedoch die perf report
für -e cpu/tx-abort/
auf die intuitiv korrekten Montagelinien hin: eine xabort
Anweisung für das erste Beispiel und eine syscall
eine für die zweite. In der realen Code-Basis, die perf Bericht zeigt auf einen Stapel schieben gleich zu Beginn einer Funktion:
: 00000000004167e0 <myns::myfun()>:
100.00 : 4167e0: push %rbp
0.00 : 4167e1: mov %rsp,%rbp
0.00 : 4167e4: push %r15
Ich habe auch den gleichen Befehl unter der Intel Software-Entwicklung Emulator laufen. Es stellt sich heraus, dass das Problem in diesem Fall wegfällt: Ich bekomme keinen Abbruch, soweit es die Anwendung betrifft.
Können Sie Ihre Transaktionsschleife buchen? –
Hallo Matthew. Leider ist es eine ziemlich große Schleife (über mehrere Funktionsaufrufe, einige der Funktionen sind textuell groß, obwohl der tatsächliche Ausführungspfad nicht sein muss). – orm
Ist es möglich, dass Sie die Schleife abschneiden, um zu sehen, was das auslöst? Das klingt wie ein zufälliger Systemaufruf irgendwo ... obwohl Ihre perf Ergebnisse etwas bizarr erscheinen. –