Цикл по строкам матрицы, на каждой итерации вызов подпрограммы со строкой a(i, :). Ответ верный, скорость позорная. Время уходит не в арифметику, а в копирование.
subroutine scale(v, n)
integer, intent(in) :: n
real, intent(inout) :: v(n)
v = 2.0 * v
end subroutine scale
! caller, a is m by n
do i = 1, m
call scale(a(i, :), n)
end do
Формальный аргумент явной формы вроде v(n) предполагает один непрерывный кусок памяти. Строка в Fortran не непрерывна, соседние элементы отстоят друг от друга на целый столбец. Поэтому gfortran на каждом вызове заводит временный массив, копирует туда строку, а после вызова обратно. Две копии на итерацию, и по умолчанию об этом ни слова.
-Warray-temporaries показывает такое место при компиляции, а -fcheck=array-temps сообщает о временном массиве во время выполнения. Оба флага теперь в отладочной сборке. Переделывать ли все такие подпрограммы под v(:) или менять порядок обхода, пока не решено.