Die Sprachen haben ähnliche Funktionen. Der Leistungsunterschied ergibt sich aus der Tatsache, dass laut Fortran Aliasing nicht zulässig ist, es sei denn, eine EQUIVALENCE-Anweisung wird verwendet. Jeder Code mit Aliasing ist kein gültiger Fortran, aber es liegt am Programmierer und nicht am Compiler, diese Fehler zu erkennen. Daher ignorieren Fortran-Compiler ein mögliches Aliasing von Speicherzeigern und ermöglichen es ihnen, effizienteren Code zu generieren. Schauen Sie sich dieses kleine Beispiel in C an:
void transform (float *output, float const * input, float const * matrix, int *n)
{
int i;
for (i=0; i<*n; i++)
{
float x = input[i*2+0];
float y = input[i*2+1];
output[i*2+0] = matrix[0] * x + matrix[1] * y;
output[i*2+1] = matrix[2] * x + matrix[3] * y;
}
}
Diese Funktion würde nach der Optimierung langsamer als das Fortran-Gegenstück ausgeführt. Warum so? Wenn Sie Werte in das Ausgabearray schreiben, können Sie die Werte der Matrix ändern. Schließlich könnten sich die Zeiger überlappen und auf denselben Speicherbereich zeigen (einschließlich des int
Zeigers!). Der C-Compiler ist gezwungen, die vier Matrixwerte für alle Berechnungen aus dem Speicher neu zu laden.
In Fortran kann der Compiler die Matrixwerte einmal laden und in Registern speichern. Dies ist möglich, da der Fortran-Compiler davon ausgeht, dass sich Zeiger / Arrays im Speicher nicht überlappen.
Glücklicherweise wurden das restrict
Schlüsselwort und das strikte Aliasing in den C99-Standard eingeführt, um dieses Problem zu beheben. Es wird heutzutage auch in den meisten C ++ - Compilern gut unterstützt. Mit dem Schlüsselwort können Sie dem Compiler einen Hinweis geben, dass der Programmierer verspricht, dass ein Zeiger keinen Alias mit einem anderen Zeiger hat. Das strikte Aliasing bedeutet, dass der Programmierer verspricht, dass sich Zeiger unterschiedlichen Typs niemals überlappen, z. B. a double*
nicht mit a int*
(mit der spezifischen Ausnahme, dass char*
und void*
mit irgendetwas überlappen können).
Wenn Sie sie verwenden, erhalten Sie die gleiche Geschwindigkeit von C und Fortran. Die Möglichkeit, das restrict
Schlüsselwort nur mit leistungskritischen Funktionen zu verwenden, bedeutet jedoch, dass C- (und C ++) Programme viel sicherer und einfacher zu schreiben sind. Betrachten Sie beispielsweise den ungültigen Fortran-Code : CALL TRANSFORM(A(1, 30), A(2, 31), A(3, 32), 30)
, den die meisten Fortran-Compiler ohne Vorwarnung gerne kompilieren, der jedoch einen Fehler verursacht, der nur bei einigen Compilern, auf einigen Hardwarekomponenten und mit einigen Optimierungsoptionen auftritt.