2013-11-29 3 views
0

Я проделал большую работу с интерпретируемыми на основе массивов языками, но я смотрю на Fortran. То, что только что произошло со мной после написания моего первого бита кода, - это вопрос о том, будет ли gfortran оптимизировать выражение с использованием синтаксиса массива, поместив выражение в один цикл. В большинстве интерпретаторов на основе массивов выражение, такое как A = B/n * 2 * pi (где B - массив), потребует 5 циклов и временных рядов массивов для оценки. Является ли gfortran достаточно умным, чтобы оптимизировать это, и будет ли мой код ниже (строка, которая вычисляет массив от 0 до 2pi), так же эффективна, как явный цикл do вокруг выражения? Есть ли что-нибудь, что я должен учитывать при использовании синтаксиса массива, если меня беспокоит производительность?Преобразовывает ли fortran 90 (gfortran) синтаксис массива?

PROGRAM Sine 
    IMPLICIT NONE 

    REAL, PARAMETER :: PI = 3.415926535 
    INTEGER, PARAMETER :: z = 500 
    INTEGER :: ier 
    INTEGER, EXTERNAL :: PGBEG 
    REAL, DIMENSION(z) :: x,y 

    x=(indgen(z)-1.0)/z*(2*pi) ! This line...`` 
    y=sin(x) 
    CALL plot(y,x) 

    CONTAINS 

    FUNCTION indgen(n) result(i) 
     INTEGER :: n 
     INTEGER, DIMENSION(n) :: i 
     INTEGER :: l 
     DO l=1,n 
      i(l)=l 
     END DO 
    END FUNCTION indgen 

    SUBROUTINE plot(y,x) 
     REAL, DIMENSION(:) :: x,y 
     ier=PGBEG(0,'/XWINDOW',1,1) 
     CALL PGENV(0.0,7.0,-1.0,1.0,0,1) 
     CALL PGLINE(SIZE(x),x,y) 
     CALL PGEND() 
    END SUBROUTINE plot 

END PROGRAM Sine 

ответ

2

В gfortran вы можете использовать флаг -Warray-temporaries, чтобы увидеть все созданные временные массивы. Когда я попробую ваш пример, не создается лишний массив временного характера (кроме того, который необходим для хранения результатов indgen (z)), поэтому я думаю, что gfortran достаточно умен.

0

Да. Фортран компилируется, а не интерпретируется. Он отлично работает с петлями.

+0

Спасибо, но это не ответ на мой вопрос. Я не прошу, если компилятор лучше обрабатывает циклы, чем интерпретатор, я пытаюсь выяснить, включает ли это выражение в один цикл, а не выполняет каждую операцию, как и во многих интерпретируемых языках массива. Думая об этом немного больше, я предполагаю, что мой код скомпилирован как минимум 2 цикла; один внутри indgen и один (или более?) для оценки остальной части выражения. –

2

Выражение z*(2*pi) является константой времени компиляции, которую компилятор может легко проверить, поэтому ее нельзя оценивать во время выполнения независимо. Кроме того, практически все современные компиляторы должны выполнять однолинейные «элементарные» операции массива в пределах одного цикла, и во многих случаях команды SIMD будут генерироваться (авто-векторизация).

Независимо от того, создается ли временное событие, зависит от того, независимо от того, обрабатывается ли каждый элемент независимо, и может ли этот компилятор доказать это. Предложение Xiaolei Zhu использования -Warray-temporaries является хорошим. Не смешивайте это с -fcheck=array-temps, который, я думаю, применим только к временным числам, генерируемым для вызовов функций.

Вот пример такого сообщения от gfortran:

foo.F90:4.12: 

foo(1:20) = 2*foo(20:1:-1) 
      1 
Warning: Creating array temporary at (1) 

вызова Вашей функции будет осуществляться в отдельном цикле, если компилятор не может встраивать его. Независимо от того, является ли компилятор строкой короткой функции, может быть довольно непредсказуемым; он потенциально зависит от того, где определена другая функция, независимо от того, имеет ли функция атрибут pure (хотя на практике это редко кажется существенным), поставщик и версия самого компилятора и параметры, которые вы передаете. Некоторые компиляторы могут генерировать отчет для этого; как я помню, у компилятора Intel есть достойный.

Edit: Это также можно встроить выражение в этой линии довольно легко вручную, используя «подразумеваемой сделать петлю»:

x = [ (real(i)/z*(2*pi), i = 0, z-1) ] 
Смежные вопросы