Ist es möglich, einen Compiler zu entwerfen, der eine Schleife optimiert, in der auf Arrays auf alternative Weise zugegriffen wird? Zum Beispiel so:
// int[] a,b
int sum = 0;
for(int i = 0; i < n; i++)
{
sum += a[i] + b[i];
}
Mit dem üblichen sequentiellen Array-Speicher a[i]
und b[i]
kann im Speicher weit voneinander entfernt sein. Daher denke ich, dass eine gute Compileroptimierung dies erkennen a[i]
und b[i]
immer zur "gleichen" Zeit a[0] b[0] a[1] b[1] ...
zugreifen und die verschachtelten Arrays speichern würde, dh, dass ein Speicherzugriff beide a[i]
und abrufen kann b[i]
.
a[i]
undb[i]
mit einer Speicheroperation abgerufen werden muss, sondern dass sie sich für eine bessere Cache-Leistung in der Nähe des Speichers befinden.Antworten:
Es wurden einige Arbeiten durchgeführt, die Ihrer Beschreibung entsprechen. Zum Beispiel:
beschreibt eine solche Optimierung.
quelle
Die kurze Antwort in diesem Fall lautet, dass die Parallelität auf Speicherebene normalerweise ausreicht, um mehrere separate Speicherblöcke in einer solchen Schleife abzudecken. Das Verschachteln in einen einzelnen Stream würde den Prozess tatsächlich verlangsamen. Viele Caching- und externe Speicheralgorithmen setzen einen solchen Grad an Parallelität voraus.
Die längere, theoretischere Antwort lautet, dass das Caching wie eine Reihe von Aspekten der Programmausführung ist, die einfach erscheinen, sich aber im Allgemeinen als schwer vorhersehbar erweisen. Beispielsweise muss ein Cache-Block möglicherweise nur abgerufen werden, wenn ein bestimmter Prozess angehalten wird. Ein Compiler, der das vorhersagen könnte, wäre gelinde gesagt interessant.
Der einfachere Fall der Optimierung einer bekannten Folge von Zugriffen (ohne sie vorhersagen zu müssen) ist selbst NP-schwer:
Petrank und Rawitz, Die Härte der cachebewussten Datenplatzierung
quelle
Ihr Beispiel ist nicht vollständig, die Arrays werden nirgendwo deklariert und nirgendwo initialisiert.
Ich vermute, in einem allgemeinen Programmierkontext wäre diese Art der Optimierung "mehr Ärger als es wert ist". Auf die meisten Arrays wird von mehr als einem Ort aus zugegriffen, sodass ein Compiler häufig erraten muss, welcher Ort der wichtigste ist. Auch viele Arrays könnten auf diese Weise nicht geändert werden, da sie die Grenzen der Kompilierungseinheiten entweder als Parameter an Funktionen oder als globale Variablen übergeben. Schließlich würde es Debug-Informationen komplexer machen.
quelle