Falsche Freigabe und Pthreads

7

Ich habe die folgende Aufgabe, um falsches Teilen zu demonstrieren und schrieb ein einfaches Programm:

%Vor%

Ich war sehr überrascht, als ich die Ergebnisse sah (ich lief es auf meinem i5-430M Prozessor).

  • Bei falschem Teilen waren es 1020 ms.
  • Ohne falsche Freigabe war es 710 ms, nur 30% schneller statt 300% (es wurde auf einigen Seiten geschrieben, dass es schneller als 300-400% wäre).
  • Ohne pthreads zu verwenden, waren es 580 ms.

Bitte zeigen Sie mir meinen Fehler oder erklären Sie, warum es passiert.

    
Alexey Matveev 30.11.2011, 18:51
quelle

2 Antworten

18

False sharing ist ein Ergebnis von mehreren Kernen mit separaten Caches, die auf die gleiche Region des physischen Speichers zugreifen (obwohl nicht dieselbe Adresse - das wäre echte Freigabe).

Um falsches Teilen zu verstehen, müssen Sie Caches verstehen. In den meisten Prozessoren hat jeder Kern seinen eigenen L1-Cache, der kürzlich zugegriffene Daten enthält. Caches sind in "Zeilen" organisiert, bei denen es sich um Datenblöcke handelt, die normalerweise 32 oder 64 Byte lang sind (abhängig von Ihrem Prozessor). Wenn Sie von einer Adresse lesen, die sich nicht im Cache befindet, wird die gesamte Zeile aus dem Hauptspeicher (oder einem L2-Cache) in L1 gelesen. Wenn Sie in eine Adresse im Cache schreiben, wird die Zeile mit dieser Adresse als "dreckig" markiert.

Hier kommt der Sharing-Aspekt ins Spiel. Wenn mehrere Kerne von derselben Zeile lesen, können sie jeweils eine Kopie der Zeile in L1 haben. Wenn eine Kopie jedoch als fehlerhaft gekennzeichnet ist, wird die Zeile in den anderen Caches ungültig. Wenn dies nicht der Fall ist, sind Schreibvorgänge auf einem Kern möglicherweise erst viel später für andere Kerne sichtbar. Wenn also der nächste Kern das nächste Mal aus dieser Zeile liest, fehlt der Cache und die Zeile muss erneut abgerufen werden.

Falsche Freigabe tritt auf, wenn die Kerne verschiedene Adressen in derselben Zeile lesen und schreiben. Obwohl sie keine Daten teilen, verhalten sich die Caches so, wie sie sind, da sie so nahe sind.

Dieser Effekt hängt stark von der Architektur Ihres Prozessors ab. Wenn Sie einen Single-Core-Prozessor hätten, würden Sie den Effekt überhaupt nicht sehen, da es keine gemeinsame Nutzung geben würde. Wenn Ihre Cache-Zeilen länger wären, würden Sie den Effekt sowohl in den "schlechten" als auch in den "guten" Fällen sehen, da sie immer noch nahe beieinander liegen. Wenn Ihre Kerne keinen L2-Cache teilen (was ich vermute, dass sie das tun), sehen Sie vielleicht 300-400% Unterschied, wie Sie sagten, da sie bei einem Cachefehlschlag den ganzen Weg zum Hauptspeicher gehen müssten.

Vielleicht möchten Sie auch wissen, dass es wichtig ist, dass jeder Thread sowohl liest als auch schreibt (+ = statt =). Einige Prozessoren haben Write-Through Caches, was bedeutet, wenn ein Kern in eine Adresse schreibt, die sich nicht im Cache befindet, wird die Zeile nicht aus dem Speicher ausgelesen und abgerufen. Vergleichen Sie dies mit Write-Back Caches, die bei Schreibvorgängen fehlen.

    
Jay Conrod 30.11.2011, 19:10
quelle
2

Ich habe über die Uhr () -Funktion in C gegooglet. Sie gibt die Anzahl der CPU-Takte vom Start bis zum Ende an. Wenn Sie nun zwei parallele Threads ausführen, wird die Anzahl der CPU-Zyklen (Taktzyklen von CPU1 + Taktzyklen) von CPU2). Ich denke, was Sie wollen, ist eine echte Uhr. Dafür verwenden Sie clock_gettime () und Sie erhalten die erwartete Ausgabe.

Ich habe Ihren Code mit dem clock_gettime () ausgeführt. Ich habe Folgendes:

mit falscher Freigabe 874.587381 ms

ohne falsche Freigabe 331.844278 ms

sequentielle Berechnung 604.160276 ms

    
Jainam MJ 18.03.2017 18:06
quelle

Tags und Links