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).
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.