Warum gibt es separate L1-Caches für Daten und Anweisungen?
23
Ich habe gerade ein paar Folien durchgesehen und festgestellt, dass der L1-Cache (zumindest bei Intel-CPUs) zwischen Daten- und Anweisungs-Cache unterscheidet. Ich möchte wissen, warum dies so ist.
In erster Linie unterscheiden sich die im Anweisungscache gespeicherten Daten in der Regel geringfügig von den im Datencache gespeicherten Daten. Neben den Anweisungen selbst gibt es Anmerkungen zum Beispiel, wo die nächste Anweisung beginnt, um den Decodierern zu helfen. Einige Prozessoren (z. B. Netburst, einige SPARCs) verwenden einen "Trace-Cache", der das Ergebnis der Decodierung eines Befehls speichert, anstatt den ursprünglichen Befehl in seiner codierten Form zu speichern.
Zweitens vereinfacht es die Schaltung ein wenig - der Datencache muss sich mit Lesen und Schreiben befassen, aber der Anweisungscache befasst sich nur mit Lesen. (Dies ist ein Teil des Grundes, warum selbstmodifizierender Code so teuer ist. Anstatt die Daten im Anweisungscache direkt zu überschreiben, wird der Schreibvorgang über den Datencache in den L2-Cache durchgeführt, und dann wird die Zeile im Anweisungscache ungültig und erneut -aus L2 geladen).
Drittens wird die Bandbreite erhöht: Die meisten modernen Prozessoren können gleichzeitig Daten aus dem Anweisungs-Cache und dem Daten-Cache lesen. Die meisten haben auch Warteschlangen am "Eingang" zum Cache, so dass sie tatsächlich zwei Lesevorgänge und einen Schreibvorgang in einem bestimmten Zyklus ausführen können.
Viertens kann es Strom sparen. Während Sie die Speicherzellen selbst mit Strom versorgen müssen, um deren Inhalt zu erhalten, können / können einige Prozessoren einige der zugeordneten Schaltungen (Decoder und dergleichen) ausschalten, wenn sie nicht verwendet werden. Mit separaten Caches können diese Schaltkreise separat für Anweisungen und Daten hochgefahren werden, was die Wahrscheinlichkeit erhöht, dass ein Schaltkreis während eines bestimmten Zyklus nicht mit Strom versorgt wird (ich bin mir nicht sicher, ob dies bei einem x86-Prozessor der Fall ist - AFAIK, es ist eher ein ARM Sache).
Es ist auch wichtig zu erwähnen, dass Code und Daten unterschiedliche Zugriffsmuster aufweisen können. Beispielsweise weisen die Anweisungen zum Summieren aller Elemente in einem Array eine zeitliche Lokalität auf (dieselben Anweisungen werden häufig verwendet (wenn Sie dies durch eine Schleife tun)), und die Daten im Array weisen eine räumliche Lokalität auf (die folgenden Daten werden als nächstes verwendet).
Gablin
1
@gablin: Diese Unterschiede in den Mustern sprechen zwar für einen einheitlichen Cache. In einer engen Schleife, wie Sie bereits erwähnt haben, befindet sich der größte Teil des Befehls-Cache im Leerlauf. Ein einheitlicher Cache würde im Grunde die Größe des Datencaches für die Dauer der Schleife verdoppeln.
Jerry Coffin
Nicht wirklich, weil es nach dieser kleinen Schleife mehr Code ist , und das ist auch wahrscheinlich mit dem Array zu arbeiten. Das kennzeichnet sehr viel Code (zB String-Handling). Tatsächlich waren die ersten Caches in CPUs vereinheitlichte Caches - sie befanden sich zwischen der Hauptspeicherschnittstelle der CPU und dem externen Bus, der ein einfacher Ort war, um sie zu platzieren -, aber wir verwenden jetzt einen partitionierten Cache, weil er in der Praxis schneller ist .
Donal Fellows
@Donal Fellows: Ja, wirklich. Mir ist bekannt, wie früh das Caching durchgeführt wurde und warum sie in einen geteilten Cache geändert wurden.
Jerry Coffin
5
Wie bei Immobilien wird die Cache-Nutzung von drei Faktoren bestimmt: Standort, Standort, Standort. Der springende Punkt bei einem Cache ist, dass die meisten Programme Positionsmuster aufweisen: Wenn sie auf Byte 1111111 zugreifen, ist das nächste Byte, auf das sie zugreifen, wahrscheinlich 1111110 oder 1111112 und nicht so viel Byte 9999999. Die meisten Programme weisen jedoch sehr unterschiedliche Werte auf Standortmuster für ihre Anweisungen und ihre Daten. Dies bedeutet, dass es unwahrscheinlich ist, dass die Anweisungen und Daten den Cache effizient gemeinsam nutzen können. Weil Anweisungen und Daten im Speicher nicht unbedingt nahe beieinander liegen. Ein Datenzugriff würde Anweisungen aus dem Cache stoßen, und das Laden von Anweisungen würde Daten aus dem Cache stoßen.
Antworten:
Es gibt tatsächlich mehrere Gründe.
In erster Linie unterscheiden sich die im Anweisungscache gespeicherten Daten in der Regel geringfügig von den im Datencache gespeicherten Daten. Neben den Anweisungen selbst gibt es Anmerkungen zum Beispiel, wo die nächste Anweisung beginnt, um den Decodierern zu helfen. Einige Prozessoren (z. B. Netburst, einige SPARCs) verwenden einen "Trace-Cache", der das Ergebnis der Decodierung eines Befehls speichert, anstatt den ursprünglichen Befehl in seiner codierten Form zu speichern.
Zweitens vereinfacht es die Schaltung ein wenig - der Datencache muss sich mit Lesen und Schreiben befassen, aber der Anweisungscache befasst sich nur mit Lesen. (Dies ist ein Teil des Grundes, warum selbstmodifizierender Code so teuer ist. Anstatt die Daten im Anweisungscache direkt zu überschreiben, wird der Schreibvorgang über den Datencache in den L2-Cache durchgeführt, und dann wird die Zeile im Anweisungscache ungültig und erneut -aus L2 geladen).
Drittens wird die Bandbreite erhöht: Die meisten modernen Prozessoren können gleichzeitig Daten aus dem Anweisungs-Cache und dem Daten-Cache lesen. Die meisten haben auch Warteschlangen am "Eingang" zum Cache, so dass sie tatsächlich zwei Lesevorgänge und einen Schreibvorgang in einem bestimmten Zyklus ausführen können.
Viertens kann es Strom sparen. Während Sie die Speicherzellen selbst mit Strom versorgen müssen, um deren Inhalt zu erhalten, können / können einige Prozessoren einige der zugeordneten Schaltungen (Decoder und dergleichen) ausschalten, wenn sie nicht verwendet werden. Mit separaten Caches können diese Schaltkreise separat für Anweisungen und Daten hochgefahren werden, was die Wahrscheinlichkeit erhöht, dass ein Schaltkreis während eines bestimmten Zyklus nicht mit Strom versorgt wird (ich bin mir nicht sicher, ob dies bei einem x86-Prozessor der Fall ist - AFAIK, es ist eher ein ARM Sache).
quelle
Wie bei Immobilien wird die Cache-Nutzung von drei Faktoren bestimmt: Standort, Standort, Standort. Der springende Punkt bei einem Cache ist, dass die meisten Programme Positionsmuster aufweisen: Wenn sie auf Byte 1111111 zugreifen, ist das nächste Byte, auf das sie zugreifen, wahrscheinlich 1111110 oder 1111112 und nicht so viel Byte 9999999. Die meisten Programme weisen jedoch sehr unterschiedliche Werte auf Standortmuster für ihre Anweisungen und ihre Daten. Dies bedeutet, dass es unwahrscheinlich ist, dass die Anweisungen und Daten den Cache effizient gemeinsam nutzen können. Weil Anweisungen und Daten im Speicher nicht unbedingt nahe beieinander liegen. Ein Datenzugriff würde Anweisungen aus dem Cache stoßen, und das Laden von Anweisungen würde Daten aus dem Cache stoßen.
quelle