Mehrere threads und CPU-cache
Ich die Umsetzung einer image-filtering operation in C mit mehreren threads und so optimiert wie möglich. Eine Frage habe ich aber: Wenn ein Speicher zugegriffen wird, die von thread 0, und parallel, wenn Sie den gleichen Speicher zugegriffen wird, der durch die thread-1, wird es aus dem cache ? Diese Frage ergibt sich aus der Möglichkeit, dass diese zwei threads ausgeführt werden konnte in zwei unterschiedlichen Kernen der CPU. Also eine andere Weise, dies auszudrücken, ist: alle Kerne teilen sich die gleiche gemeinsame cache-Speicher ?
Angenommen ich habe ein Speicher-layout wie in der folgenden
int Ausgabe[100];
Angenommen es sind 2 CPU-Kerne und damit ich spawnen zwei threads arbeiten gleichzeitig. Ein Schema könnte sein, teilen den Speicher in zwei Stücke, und 50-99 0-49, und lassen Sie jeden Faden der Arbeit auf jedem Stück. Eine andere Möglichkeit könnte sein zu lassen, thread-0 Arbeit auf auch Indizes, wie 0 2 4 und so weiter.. während der andere thread die Arbeit auf ungeraden Indizes wie 1 3 5 .... Diese Technik später einfacher zu implementieren ist (speziell für 3D-Daten), aber ich bin nicht sicher, ob ich verwenden könnte, den cache effizient diese Weise.
- Am Ende, dieses wissen wird nicht viel helfen. Obwohl ich bin damit einverstanden, dass in der Lage zu interpretieren, Beobachtungen entsprechend, um das wissen von der CPU Innereien ist gut, am Ende sind Sie unten, um zu Messen, was schneller ist, und das anzuwenden, was Sie beobachtet, egal ob es passt in jede Theorie.
- Ich sehe keinen Grund, dieses hat eine
c++
tag (Sie haben dies Schreibe, in C, Sie sagte), so dass ich Sie entfernt. Fühlen Sie sich frei, mich anzubrüllen, wenn das war dumm.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Im Allgemeinen ist es eine schlechte Idee zu teilen überlappende Speicherbereiche, wie wenn ein thread bearbeitet 0,2,4... und die anderen Prozesse 1,3,5... Obwohl einige Architekturen unterstützen kann, die meisten Architekturen nicht, und Sie können sich wahrscheinlich nicht festlegen, auf welche Rechner Ihr code ausgeführt wird. Auch das Betriebssystem ist frei, weisen Sie Ihren code, um jeden Kern es mag (ein Einzelzimmer, zwei auf dem gleichen physischen Prozessor, oder zwei Kerne, die auf verschiedenen Prozessoren). Auch jede CPU hat in der Regel ein eigener first-level-cache, auch wenn die auf dem gleichen Prozessor.
In den meisten Situationen 0,2,4.../1,3,5... wird sich verlangsamen die Leistung extrem bis zu möglicherweise langsamer als eine single-CPU.
Herb Sutters "Vermeidung Von False-Sharing" veranschaulicht dies sehr gut.
Über das System [...n/2-1] und [n/2...n] wird die Skalierung viel besser auf den meisten Systemen. Es kann sogar dazu führen super linear performance als die Größe des Caches aller CPUs in Summe können Sie möglicherweise verwendet werden. Die Anzahl der threads verwendet werden sollte immer konfigurierbar und sollte standardmäßig die Anzahl der Prozessor-Kerne gefunden.
Die Antwort auf diese Frage hängt stark von der Architektur und der cache-Ebene, zusammen mit, wo die threads sind.
Beispielsweise aktuelle Intel multi-core-CPUs einen L1-caches, das sind pro Kern und einem L2-cache, der gemeinsam von Kernen, die sich im selben CPU package; verschiedene CPU-Pakete haben Ihre eigenen L2-caches.
Sogar in dem Fall, wenn Ihre threads laufen auf zwei Kerne in einem Paket, obwohl, wenn beide threads Zugriff auf Daten innerhalb derselben cacheline, die Sie haben, die cacheline Prellen zwischen den beiden L1-caches. Diese ist sehr ineffizient, und Sie sollten Ihre design-Algorithmus um diese situation zu vermeiden.
Wenige Kommentare haben gefragt, wie gehen Sie zur Vermeidung dieses Problems.
Am Herzen, es ist wirklich nicht besonders kompliziert - Sie wollen einfach nur, um zu vermeiden, zwei threads gleichzeitig versuchen, auf Daten zuzugreifen, die sich auf die gleiche cache-Zeile ein, wobei mindestens ein thread schreibt die Daten. (Solange alle threads sind nur Lesen der Daten, es gibt kein problem - auf den meisten Architekturen, nur-lese-Daten vorhanden sein können, in mehreren caches).
Um dies zu tun, müssen Sie wissen, die cache-line-Größe - dies variiert abhängig von der Architektur, aber derzeit die meisten x86 und x86-64-Familie-chips verwenden einen 64-byte-cache-Zeile (Fragen Sie Ihren Architektur-Handbuch für andere Architekturen). Sie müssen auch wissen, die Größe der Daten-Strukturen.
Wenn Sie Fragen Sie Ihren compiler an, richten Sie die freigegebenen Daten-Struktur von Interesse, um eine 64-byte-Begrenzung (zum Beispiel dein array
output
), dann wissen Sie, dass es startet beim start einer cache-Zeile, und Sie können auch berechnen, in denen die nachfolgenden cache-line-Grenzen sind. Wenn Ihrint
4 bytes, wird dann jeder cacheline enthält genau 8int
Werte. Solange das array beginnt auf einer cacheline Grenze, dannoutput[0]
durchoutput[7]
wird auf eine cache-Zeile, undoutput[8]
durchoutput[15]
auf die nächste. In diesem Fall würden Sie Ihre design-Algorithmus, so dass jeder thread einen block von benachbartenint
Werte, die ein Vielfaches von 8.Wenn Sie die Speicherung kompliziert
struct
Typen lieber als nurint
, diepahole
- Dienstprogramm verwenden. Es analysiert diestruct
Typen in der kompilierten binären, und zeigen Sie das layout (einschließlich der Polsterung) und Gesamtgröße. Sie können dann stellen Sie Ihrestruct
s mit dieser Ausgabe - für Beispiel, können Sie manuell fügen Sie etwas Polsterung, so dass Ihrestruct
ist ein Vielfaches der cache-line-Größe.Auf POSIX-Systemen, die
posix_memalign()
Funktion ist nützlich für das zuweisen von einen block von Speicher, die mit einer bestimmten Ausrichtung.y_size * x_size
würde ein Vielfaches von 8.Ich könnte verkennen, aber ob der core cache-Speicher freigegeben ist oder nicht, hängt von der Implementierung auf der CPU. Sie würden schauen müssen, bis die technischen Blätter auf der Seite des Herstellers, um zu überprüfen, ob jeder Kern in deiner CPU hat Ihren eigenen cache oder ob der cache freigegeben wurde.
Arbeitete ich auf Bildbearbeitung als auch für ein security-Unternehmen, und manchmal bekamen wir beschädigte Bilder nach dem ausführen der batch-Operationen auf threads. Nach langen Untersuchungen kamen wir zu dem Schluss, dass der cache war geteilt zwischen CPU-Kern und, in seltenen Fällen die Daten beeing überschrieben oder ersetzt mit falschen Daten.
Ob dies ist etwas, um in Betracht oder ist eher ein Seltenes Ereignis, ich kann nicht anwser.
Intel-Dokumentation
Intel veröffentlicht pro-generation Datenblätter enthalten können, diese Art von Informationen.
Beispielsweise für den Prozessor i5-3210M, die hatte ich auf meinem älteren computer, ich schaue auf die 3. generation - Datasheet-Volume 1 3.3 "Intel Hyper-Threading-Technologie (Intel HT-Technologie)", sagt:
welche bestätigt, dass die caches werden gemeinsam in einer gegebenen hyperthread für die generation der CPUs.
Siehe auch: