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