Мови мають подібні набори функцій. Різниця в продуктивності пов'язана з тим, що Fortran каже, що дозвол не дозволений, якщо не буде використано оператор EQUIVALENCE. Будь-який код, який має псевдонім, не є дійсним Fortran, але це визначає помилки, а не програміст, а не компілятор. Таким чином, компілятори Fortran ігнорують можливе псевдонім покажчиків пам'яті і дозволяють їм генерувати більш ефективний код. Погляньте на цей невеликий приклад на С:
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;
}
}
Ця функція працюватиме повільніше, ніж аналог Fortran після оптимізації. Чому так? Якщо ви записуєте значення у вихідний масив, ви можете змінити значення матриці. Зрештою, вказівники можуть перекриватися і вказувати на той самий шматок пам'яті (включаючи int
вказівник!). Компілятор C змушений перезавантажити чотири значення матриці з пам'яті для всіх обчислень.
У Fortran компілятор може один раз завантажити матричні значення і зберегти їх у регістри. Це може зробити так, оскільки компілятор Fortran передбачає, що вказівники / масиви не перетинаються в пам'яті.
На щастя, restrict
ключове слово та суворе псевдонім було введено до стандарту C99 для вирішення цієї проблеми. Він добре підтримується в більшості компіляторів C ++ і в наші дні. Ключове слово дозволяє дати компілятору підказку, що програміст обіцяє, що покажчик не має псевдоніму з будь-яким іншим вказівником. Строгий-альясінг означає , що програміст обіцяє , що покажчики різного типу ніколи не перекривається, наприклад, double*
НЕ буде перекриватися з int*
(з конкретного винятку того, що char*
і void*
може перекриватися з чим - або).
Якщо ви їх використовуєте, ви отримаєте однакову швидкість від C і Fortran. Однак можливість використання restrict
ключового слова лише з критичними функціональними функціями означає, що програми C (і C ++) набагато безпечніше і простіше писати. Наприклад, розглянемо недійсний код Fortran:, CALL TRANSFORM(A(1, 30), A(2, 31), A(3, 32), 30)
який більшість компіляторів Fortran з радістю буде компілювати без будь-якого попередження, але вводить помилку, яка відображається лише на деяких компіляторах, на деяких апаратних засобах та з деякими параметрами оптимізації.