Fortran-DVM - оглавление Часть 1(1-4) Часть 2 (5-6) Часть 3 (7-15) Часть 4
(Приложения)
создан: октябрь, 2009 - последнее обновление 01.12.09 -

Приложение 1. Синтаксис

2.2. Синтаксис директив FDVM

directive-line

is       !DVM$  dvm-directive

 

or    CDVM$  dvm-directive

 

or     *DVM$  dvm-directive

 

dvm-directive

is    specification-directive

 

or   executable-directive

 

specification-directive

is    processors-directive

 

or   align-directive

 

or   distribute-directive

 

or   template-directive

 

or   pointer-directive

 

or   shadow-directive

 

or   dynamic-directive

 

or   inherit-directive

 

or   remote-group-directive

 

or   reduction-group-directive

 

or   consistent-directive

 

or   consistent-group-directive

 

or   task-directive

 

or   heap-directive

 

or   asyncid-directive

 

executable-directive

is    realign-directive

 

or   redistribute-directive

 

or   parallel-directive

 

or   remote-access-directive

 

or   shadow-group-directive

 

or   shadow-start-directive

 

or   shadow-wait-directive

 

or   reduction-start-directive

 

or   reduction-wait-directive

 

or   consistent-start-directive

 

or   consistent-wait-directive

 

or   new-value-directive

 

or   prefetch-directive

 

or   reset-directive

 

or   parallel-task-loop-directive

 

or   map-directive

 

or   task-region-directive

 

or   end-task-region-directive

 

or   on-directive

 

or   end-on-directive

 

or   f90-directive

 

or   asynchronous-directive

 

or   end-asynchronous-directive

 

or   asyncwait-directive

Ограничения:

Выражение спецификации – это выражение, в котором каждое первичное должно быть одной из следующих форм:

1)      константа,

2)      переменная, которая является формальным аргументом,

3)      переменная из COMMON блока,

4)      ссылка на встроенную функцию, где каждый аргумент является выражением спецификации,

5)      выражение спецификации, заключенное в скобки.

3.  Массивы виртуальных процессоров. Директива PROCESSORS

processors-directive

is   PROCESSORS  processors-decl-list

processors-decl

is   processors-name  ( explicit-shape-spec-list )

explicit-shape-spec

is   [ lower-bound : upper-bound

lower-bound

is    int-expr

upper-bound

is    int-expr

Ограничения.

4.1. Директивы DISTRIBUTE и REDISTRIBUTE

distribute-directive

is   dist-action  distributee  dist-directive-stuff

 

or  dist-action [ dist-directive-stuff ] :: distributee-list

 

dist-action

is   DISTRIBUTE

 

or  REDISTRIBUTE

 

dist-directive-stuff

is   dist-format-list  [   dist-onto-clause  ]

 

distributee

is   array-name

 

or  pointer-name

 

or  template-name

 

dist-format

is   BLOCK

 

or  GEN_BLOCK ( block-size-array )

 

or  WGT_BLOCK ( block-weight-array , nblock)

 

or  MULT_BLOCK ( divisor )

 

or   *

 

dist-onto-clause

is   ONTO  dist-target

 

dist-target

is   processors-name [(processors-section-subscript-list )]

 

or  task-name ( task-index )

 

 

 

processors-section-subscript

is    [ subscript ] : [ subscript ]

 

 

 

subscript

is   int-expr

 

 

 

divisor

is   int-expr

 

 

nblock

is   int-expr

 

 

block-size-array

is   array-name

 

 

block-weight-array

is   array-name

Ограничения:

4.3.1. Директивы ALIGN и REALIGN

align-directive

is   align-action  alignee  align-directive-stuff

 

or  align-action [ align-directive-stuff ] ::  alignee‑list

align-action

is   ALIGN

 

or  REALIGN

 

 

align-directive-stuff

is   ( align-source-list )  align-with-clause

 

 

alignee

is    array-name

 

or   pointer-name

 

align-source

is    *

 

or   align-dummy

 

align-dummy

is    scalar-int-variable

 

align-with-clause

is   WITH  align-spec

 

 

align-spec

is    align-target   ( align-subscript-list  )

 

align-target

is    array-name

 

or    template-name

 

or    pointer-name

 

align-subscript

is     int-expr

 

or    align-dummy-use

 

or    *

 

align-dummy-use

is   [ primary-expr * align‑dummy [ add-op  primary-expr ]

 

primary-expr

is    int-constant

 

or   int-variable

 

or   ( int-expr )

 

 

add-op

is    +

 

or   -

Ограничения:

4.3.2. Директива TEMPLATE

template-directive

is   TEMPLATE  template-decl-list

 

template-decl

is    template-name  [ ( explicit-shape-spec-list ) ]

4.4. Директивы DYNAMIC и NEW_VALUE

dynamic-directive

is    DYNAMIC  alignee-or-distributee-list

 

 

alignee-or-distributee

is    alignee

 

or   distribute

 

new-value-directive

is    NEW_VALUE

5.1.2. Распределение витков цикла. Директива PARALLEL

parallel-directive

is    PARALLEL   ( do-variable-list )

       ON    iteration-align-spec  

[  ,  new-clause ] [ ,  reduction-clause]

[ ,  shadow-renew-clause] [ ,  shadow-compute-clause]

[ ,  remote-access-clause ] [ ,  across-clause ]

[ ,  consistent-clause ]

 

iteration-align-spec

is    align-target  ( iteration-align-subscript-list )

 

iteration-align-subscript

is    int-expr

 

or   do-variable-use

 

or    *

 

 

do-variable-use

is   [ primary-expr  * ] do-variable [ add-op  primary-expr ]

5.1.3. Приватные переменные. Спецификация NEW

new-clause

is    NEW   new-variable-list  )

 

new-variable

is     array-name

 

or    scalar-variable-name

Ограничение:

·         NEW-переменные  не могут быть распределенными массивами.

5.1.4. Редукционные операции и переменные. Спецификация REDUCTION

reduction-clause

is    REDUCTION

                  ( [ reduction-group-name : ] reduction-op-list  )

 

reduction-op

is    reduction-op-name  (  reduction-variable )

 

or   reduction-loc-name ( reduction-variable ,

                                         location-variable, int-expr)

 

reduction-variable

is     array-name

 

or    scalar-variable-name

 

location-variable

is     array-name

 

reduction-op-name

is     SUM

 

or    PRODUCT

 

or    MAX

 

or    MIN

 

or    AND

 

or    OR

 

or     EQV

 

or     NEQV

 

reduction-loc-name

is      MAXLOC

 

or     MINLOC

Ограничение:

·         Редукционные переменные вычисляются и используются только в операторах определенного вида - редукционных операторах.

6.2.1.Спецификация массива с теневыми гранями

shadow-directive

is    SHADOW  dist-array ( shadow-edge-list )

 

or   SHADOW ( shadow-edge-list ) :: dist-array-list

 

dist-array

is    array-name

 

or   pointer-name

 

shadow-edge

is     width

 

or     low-width  high-width

 

width

is     int-expr

 

low-width

is      int-expr

 

high-width

is      int-expr

Ограничения:

6.2.2. Синхронная спецификация независимых ссылок типа SHADOW для одного цикла

shadow-renew-clause

is   SHADOW_RENEW   ( renewee‑list )

 

or   shadow-start-directive

 

or   shadow-wait-directive

 

renewee

is   dist-array-name  [ ( shadow-edge-list ) ]  (CORNER) ]

Ограничения:

6.2.3. Вычисление значений в теневых гранях. Спецификация SHADOW_COMPUTE

shadow-compute-clause

is   SHADOW_COMPUTE [( dist-array-name

                                                 ( shadow-edge-list ) )]

6.2.4. Спецификация AСROSS зависимых ссылок типа SHADOW для одного цикла

across-clause

is    ACROSS  dependent-array-list  )

 

dependent-array

is    dist-array-name  (  dependence-list  ) [(section-spec-list)]

 

dependence

is    flow-dep-length : anti-dep-length

 

 

 

 

flow-dep-length

is    int-constant

 

 

 

 

anti-dep-length

is    int-constant

 

 

 

section-spec

is   SECTION ( section-subscript-list )

Ограничение:

·         В каждой ссылке на массив может существовать зависимость по данным только по одному распределенному измерению.

6.2.5. Асинхронная cпецификация независимых ссылок типа SHADOW

shadow-group-directive

is   SHADOW_GROUP  shadow-group-name ( renewee-list )

 

shadow-start-directive

is   SHADOW_START  shadow-group-name

 

shadow-wait-directive

is   SHADOW_WAIT   shadow-group-name

Ограничения.

6.3.1. Директива REMOTE_ACCESS

remote-access-directive

is    REMOTE_ACCESS 

       ( [ remote-group-name   ] regular-reference-list)

 

 

regular-reference

is    dist-array-name [( regular-subscript-list )]

 

 

regular-subscript

is    int-expr

 

or   do-variable-use

 

or   :

 

 

remote-access-clause

is   remote-access-directive

6.3.3. Асинхронная спецификация удаленных ссылок типа REMOTE

remote-group-directive

is    REMOTE_GROUP  remote-group-name-list

Ограничение:

·         Идентификатор, определенный этой директивой, может использоваться только в директивах REMOTE_ACCESS , PREFETCH и RESET

prefetch-directive

is   PREFETCH  remote-group-name

 

 

reset-directive

is    RESET     remote-group-name

Ограничения.

6.3.4.2.1. Директива ASYNCID

asyncid-directive

is   ASYNCID async-name-list

 

 

6.3.4.2.2. Директивы ASYNCHRONOUS и END ASYNCHRONOUS

asynchronous-construct

is   asynchronous-directive

 

                    copy-statement

                   [ copy-statement ] …

 

    end-asynchronous-directive

 

 

asynchronous-directive

is   ASYNCHRONOUS async-name

 

 

end-asynchronous-directive

is   END ASYNCHRONOUS

6.3.4.2.3. Директива ASYNCWAIT

asyncwait-directive

is    ASYNCWAIT async-name

6.4.2. Асинхронная спецификация удаленных ссылок типа REDUCTION

reduction-group-directive

is   REDUCTION_GROUP  reduction-group-name-list

 

reduction-start-directive

is   REDUCTION_START  reduction-group-name

 

reduction-wait-directive

is   REDUCTION_WAIT   reduction-group-name

Ограничения.

7.1. Описание массива задач

task-directive

is   TASK  task-list

 

 

task

is   task-name ( max-task )

 

 

7.2. Отображение задач на процессоры. Директива MAP

map-directive

is  MAP task-name ( task-index )

 

    ONTO  processors-name( processors-section-subscript-list)

7.4. Распределение вычислений. Директива TASK_REGION

block-task-region

is   task-region-directive

 

              on-block

 

            [ on-block ]...

 

       end-task-region-directive

 

 

task-region-directive

is   TASK_REGION  task-name  [ , reduction-clause ]

 

       [ ,  consistent-clause ]

 

 

end-task-region-directive

is    END  TASK_REGION

 

 

on-block

is   on-directive

 

             block

 

      end-on-directive

 

 

on-directive

is   ON   task-name ( task-index ) [ , new-clause ]

 

 

end-on-directive

is   END ON

 

 

loop-task-region

is   task-region-directive

 

              parallel-task-loop

 

      end-task-region-directive

 

 

parallel-task-loop

is   parallel-task-loop-directive

 

                   do-loop

 

 

parallel-task-loop-directive

is   PARALLEL ( do-variable

      ON  task-name ( do-variable [ , new-clause ]

8.3.1.  Директива CONSISTENT

consistent-directive

is   CONSISTENT  array-name-list 

 8.3.2.  Опция CONSISTENT

consistent-clause

is   CONSISTENT 

       ([consistent-group-name : ] array-reference-list)

array-reference

is   array-name  ( regular-subscript-list )

regular-subscript

is   int-expr

 

or    do-variable-use

 

or    :

8.3.3.  Спецификация асинхронного выполнения приведения в консистентное состояние

consistent-group-directive

is   CONSISTENT_GROUP consistent-group-name-list

consistent-start-directive

is   CONSISTENT_START consistent-group-name

consistent-start-directive

is   CONSISTENT_WAIT consistent-group-name

9.  Процедуры

inherit-directive

is   INHERIT   dummy-array-name-list

 Приложение 2. Примеры программ

Семь небольших программ из научной области приводятся для иллюстрации свойств языка Fortran DVM. Они предназначены для решения систем линейных уравнений:

A x = b

где       A – матрица коэффициентов,

b – вектор свободных членов,

x – вектор неизвестных.

Для решения этой системы используются следующие основные методы.

Прямые методы. Хорошо известный метод исключения Гаусса является наиболее широко используемым алгоритмом этого класса. Основная идея алгоритма заключается в преобразовании матрицы А в верхнетреугольную матрицу и использовании затем обратной подстановки, чтобы привести ее к диагональной форме.

Явные итерационные методы. Наиболее известным алгоритмом этого класса является метод релаксации Якоби. Алгоритм выполняет следующие итерационные вычисления

xi,jnew  = (xi-1,jold    + xi,j-1old   +  xi+1,jold   + xi,j+1old  ) / 4

Неявные итерационные методы. К этому классу относится метод последовательной верхней релаксации. Итерационное приближение вычисляется по формуле

xi,jnew  = ( w / 4 ) * (xi-1,jnew    + xi,j-1new   +  xi+1,jold   + xi,j+1old  ) + (1-w) * xi,jold

При использовании "красно-черного" упорядочивания переменных каждый итерационный шаг разделяется на два полушага Якоби. На одном полушаге вычисляются значения "красных" переменных, на другом – "черных" переменных. "Красно-черное" упорядочивание позволяет совместить вычисления и обмены данными.

Пример 1. Алгоритм метода исключения Гаусса

                   PROGRAM GAUSS

     C                   решение системы линейных уравнений  A´ x = b

                   PARAMETER   ( N = 100 )

                   REAL   A( N, N+1 ), X( N )

     C            A :   матрица коэффициентов  (N,N+1).

     C                   вектор правых частей линейных уравнений хранится

     C                   в (N+1)-ом столбце матрицы A

     C            X :   вектор неизвестных

     C            N :   число линейных уравнений

     CDVM$  DISTRIBUTE   A  ( BLOCK,  *)

     CDVM$  ALIGN   X(I)   WITH   A(I, N+1)

     C

     C                Инициализация

     C

     *DVM$   PARALLEL  ( I )   ON   A( I , * )

                   DO  100  I = 1, N

                   DO  100  J = 1, N+1

                        IF  (( I .EQ. J )      THEN

                                   A( I, J ) = 2.0

                        ELSE

                          IF ( J .EQ. N+1)  THEN

                                   A( I, J ) = 0.0

                        ENDIF

                        ENDIF

     100         CONTINUE

     C

     C                Исключение

     C

                   DO  1  I = 1, N

     C                   I-ая строка матрицы  A  буферизуется перед

     C                   обработкой I-ого уравнения, и ссылки  A(I,K), A(I, I)

     C                   заменяются соответствующими ссылками на буфер

     *DVM$   PARALLEL  ( J )  ON  A( J, * ) , REMOTE_ACCESS  (A ( I, : ))

                        DO  5  J  = I+1, N

                        DO  5  K = I+1, N+1

                                   A( J, K ) = A( J, K ) - A( J, I )  *  A( I, K ) / A( I, I )

     5                 CONTINUE

     1             CONTINUE

     C                   сначала вычисляется X(N)

                   X( N ) = A( N, N+1 ) / A( N, N )

     C

     C                   Нахождение X(N-1), X(N-2), ...,X(1) обратной подстановкой

     C

                   DO  6  J = N-1, 1, -1

     C                   (J+1)-ый элемент массива X буферизуется перед

     C                   обработкой J-ого уравнения, и ссылка X(J+1)

     C                   заменяется соответствующей ссылкой на буфер

     *DVM$   PARALLEL  ( I )  ON  A( I , * ) , REMOTE_ACCESS  ( X( J+1 ))

                        DO  7  I = 1, J

                                   A( I, N+1 )  = A( I, N+1 ) - A( I,  J+1 ) * X( J+1 )

     7                 CONTINUE

                        X( J ) = A( J,  N+1 ) / A( J, J)

     6             CONTINUE

                   PRINT *,  X

                   END

 Пример 2. Алгоритм Якоби

                   PROGRAM    JACOB

                   PARAMETER    (K=8,  ITMAX=20)

                   REAL     A(K,K), B(K,K), EPS, MAXEPS

     CDVM$  DISTRIBUTE   A  ( BLOCK,   BLOCK)

     CDVM$  ALIGN   B( I, J )  WITH  A( I, J )

     C                массивы A и B распределяются блоками

                   PRINT *,  '**********  TEST_JACOBI   **********'

                   MAXEPS  =  0.5E - 7

     CDVM$  PARALLEL    (J,I)   ON   A(I, J)

     C                гнездо из двух параллельных циклов, итерация (i,j) выполняется,

     C                на том процессоре, где размещен элемент A(i,j)

                   DO  1   J  =  1, K

                   DO  1   I  =  1, K

                   A(I,  J)  =  0.

                   IF(I.EQ.1 .OR. J.EQ.1 .OR. I.EQ.K .OR. J.EQ.K) THEN

                        B(I,  J) = 0.

                   ELSE

                        B(I,  J)  = ( 1. + I + J )

                   ENDIF

     1             CONTINUE

                   DO  2   IT  =  1,  ITMAX

                   EPS  =  0.

     CDVM$  PARALLEL  (J,  I)   ON  A(I,  J),  REDUCTION ( MAX( EPS ))

     C                переменная EPS используется для вычисления максимального значения

                   DO  21  J  =  2, K-1

                   DO  21  I  =  2, K-1

                        EPS = MAX ( EPS,  ABS( B( I, J)  -  A( I, J)))

                        A(I, J)  =  B(I, J)

     21           CONTINUE

     CDVM$  PARALLEL  (J,  I)   ON  B(I,  J),   SHADOW_RENEW   (A)

     C                копирование теневых элементов массива A

     C                с соседних процессоров перед выполнением цикла

                   DO  22  J = 2,  K-1

                   DO  22  I = 2,  K-1

                        B(I, J) =  (A( I-1, J ) + A( I, J-1 ) + A( I+1, J) + A( I, J+1 )) / 4

     22           CONTINUE

                   PRINT *,  'IT = ', IT,  '   EPS = ', EPS

                   IF ( EPS . LT . MAXEPS )    GO TO   3

     2             CONTINUE

     3             OPEN (3,  FILE='JACOBI.DAT',  FORM='FORMATTED')

                   WRITE (3,*)   B

                   CLOSE (3)

                   END

Пример 3. Алгоритм Якоби (асинхронный вариант)

                   PROGRAM    JACOB1

                   PARAMETER    (K=8,  ITMAX=20)

                   REAL     A(K,K), B(K,K), EPS, MAXEPS

     CDVM$  DISTRIBUTE   A  ( BLOCK,   BLOCK)

     CDVM$  ALIGN   B( I, J )  WITH  A( I, J )

     C                массивы A и B распределяются блоками

     CDVM$  REDUCTION_GROUP    REPS

 

                   PRINT *,  '**********  TEST_JACOBI_ASYNCHR   **********'

     CDVM$  SHADOW_GROUP   SA ( A )

      C                      создание группы теневых граней

                   MAXEPS  =  0.5E - 7

     CDVM$  PARALLEL    (J,I)   ON   A(I, J)

     C                 параллельный цикл для инициализации массивов А и В

                   DO  1   J  =  1, K

                   DO  1   I  =  1, K

                   A(I,  J)  =  0.

                   IF(I.EQ.1 .OR. J.EQ.1 .OR. I.EQ.K .OR. J.EQ.K) THEN

                        B(I,  J) = 0.

                   ELSE

                        B(I,  J)  = ( 1. + I + J )

                   ENDIF

     1             CONTINUE

                   DO  2   IT  =  1,  ITMAX

                   EPS  =  0.

     C                создается группа редукционных операций

     C                и начальные значения редукционных переменных запоминаются

     CDVM$  PARALLEL  (J,  I)   ON  A(I,  J),  SHADOW_START  SA ,

     CDVM$*    REDUCTION_GROUP   ( REPS :  MAX( EPS ))

 

     C                изменяется порядок выполнения витков цикла:

     C                сначала вычисляются и посылаются граничные элементы массива A,

     C                затем вычисляются внутренние элементы массива A

                   DO  21  J  =  2, K-1

                   DO  21  I  =  2, K-1

                        EPS = MAX ( EPS,  ABS( B( I, J)  -  A( I, J)))

                        A(I, J)  =  B(I, J)

     21           CONTINUE

     CDVM$  REDUCTION_START     REPS

     C                начало редукционной операции над частичными результатами,

     C                вычисленными в копиях переменной EPS на каждом процессоре

     CDVM$  PARALLEL  (J,  I)   ON  B(I,  J),   SHADOW_WAIT   SA

     C                изменяется порядок выполнения витков цикла:

     C                сначала вычисляются внутренние элементы массива B , затем принимаются

     C                от соседних процессоров теневые элементы массиваA,

     C                а потом вычисляются граничные элементы массива B

                   DO  22  J = 2,  K-1

                   DO  22  I = 2,  K-1

                        B(I, J) =  (A( I-1, J ) + A( I, J-1 ) + A( I+1, J) + A( I, J+1 )) / 4

     22           CONTINUE

     CDVM$  REDUCTION_WAIT     REPS

     C                ожидается результат выполнения редукционной операции

                   PRINT *,  'IT = ', IT,  '   EPS = ', EPS

                   IF ( EPS . LT . MAXEPS )    GO TO   3

     2             CONTINUE

     3             OPEN (3,  FILE='JACOBI.DAT',  FORM='FORMATTED')

                   WRITE (3,*)   B

                   CLOSE (3)

                   END

Пример 4. Последовательная верхняя релаксация

                   PROGRAM  SOR

                   PARAMETER  ( N = 100 )

                   REAL   A( N, N ),  EPS,  MAXEPS, W

                   INTEGER   ITMAX

     *DVM$   DISTRIBUTE     A  ( BLOCK,  BLOCK )

                   ITMAX=20

                   MAXEPS = 0.5E - 5

                   W = 0.5

     *DVM$   PARALLEL   ( I, J )  ON  A( I,  J )

                   DO  1  I = 1, N

                   DO  1  J = 1, N

                        IF ( I .EQ.J)   THEN

                             A( I, J ) = N + 2

                        ELSE

                             A( I, J ) = -1.0

                        ENDIF

     1             CONTINUE

                   DO  2   IT = 1, ITMAX

                        EPS = 0.

     *DVM$   PARALLEL  ( I, J)   ON  A( I,  J),  NEW (S), 

     *DVM$*             REDUCTION ( MAX( EPS )),  ACROSS  (A(1:1,1:1))

     C                переменная S – приватная переменная

     С                 (ее использование локализовано в пределах одного витка)

     C                переменная EPS используется для вычисления максимума

 

                   DO  21   I = 2, N-1

                   DO  21   J = 2,  N-1

                        S = A( I, J )

                        A( I, J ) = (W / 4) * (A( I-1, J ) + A( I+1, J ) + A( I, J-1 ) +

                *      A( I, J+1 )) + ( 1-W ) * A( I, J)

                        EPS = MAX ( EPS,  ABS( S - A( I, J )))

     21           CONTINUE

                   PRINT *,  'IT = ',  IT, '   EPS = ',  EPS

                   IF    (EPS  .LT.  MAXEPS )     GO TO   4

     2             CONTINUE

     4             PRINT *, A

                   END

Пример 5. "Красно-черная" последовательная верхняя релаксация

                   PROGRAM  REDBLACK

                   PARAMETER  ( N = 100 )

                   REAL   A( N, N ),  EPS,  MAXEPS, W

                   INTEGER   ITMAX

     *DVM$   DISTRIBUTE     A  ( BLOCK,  BLOCK )

                   ITMAX=20

                   MAXEPS = 0.5E - 5

                   W = 0.5

     *DVM$   PARALLEL   ( I, J )  ON  A( I,  J )

                   DO  1  I = 1, N

                   DO  1  J = 1, N

                        IF ( I .EQ.J)   THEN

                             A( I, J ) = N + 2

                        ELSE

                             A( I, J ) = -1.0

                        ENDIF

     1             CONTINUE

                   DO  2   IT = 1, ITMAX

                        EPS = 0.

     C                цикл для красных и черных переменных

                   DO  3  IRB = 1,2

     *DVM$   PARALLEL  ( I, J)   ON  A( I,  J),  NEW (S), 

     *DVM$*             REDUCTION ( MAX( EPS )),  SHADOW_RENEW  (A)

     C                переменная S – приватная переменная

     С                 (ее использование локализовано в пределах одного витка)

     C                переменная EPS используется для вычисления максимума

 

     C            Исключение : непрямоугольное итерационное пространство

 

                   DO  21   I = 2, N-1

                   DO  21   J = 2 + MOD ( I+ IRB, 2 ),  N-1,  2

                        S = A( I, J )

                        A( I, J ) = (W / 4) * (A( I-1, J ) + A( I+1, J ) + A( I, J-1 ) +

                *      A( I, J+1 )) + ( 1-W ) * A( I, J)

                        EPS = MAX ( EPS,  ABS( S - A( I, J )))

     21           CONTINUE

     3             CONTINUE

                   PRINT *,  'IT = ',  IT, '   EPS = ',  EPS

                   IF    (EPS  .LT.  MAXEPS )     GO TO   4

     2             CONTINUE

     4             PRINT *, A

                   END

Пример 6. Статические задачи (параллельные секции)

                   PROGRAM    TASKS

     C                прямоугольная сетка разделена на две области

     C           

 

 

K

C

N1

A1, B1

C

N2

A2, B2

     C           

                   PARAMETER    (K=100,  N1 = 50,  ITMAX=10, N2 = K – N1 )

     CDVM$  PROCESSORS    P(NUMBER_OF_PROCESSORS( ))

                   REAL     A1(N1+1,K), A2(N2+1,K), B1(N1+1,K), B2(N2+1,K)

                   INTEGER  LP(2),  HP(2)

     CDVM$  TASK  MB( 2 )

     CDVM$  ALIGN   B1( I, J )  WITH  A1( I, J )

     CDVM$  ALIGN   B2( I, J )  WITH  A2( I, J )

     CDVM$  DISTRIBUTE  ::  A1, A2

     CDVM$  REMOTE_GROUP  BOUND

                   CALL  DPT(LP, HP, 2)

     C            Распределение задач (областей) по процессорам.

     C            Распределение массивов по задачам

     CDVM$  MAP  MB( 1 ) ONTO  P( LP(1) : HP(1) )

     CDVM$  REDISTRIBUTE  A1( *, BLOCK )  ONTO  MB( 1 )

     CDVM$  MAP  MB( 2 )   ONTO   P( LP(2) : HP(2) )

     CDVM$  REDISTRIBUTE  A2( *, BLOCK )  ONTO  MB( 2 )

     C                Инициализация

     CDVM$  PARALLEL    ( J, I )   ON   A1(I, J)

                   DO  10   J  =  1, K

                   DO  10   I  =  1, N1

                   IF(I.EQ.1 .OR. J.EQ.1 .OR. J.EQ.K) THEN

                        A1(I, J) = 0.

                        B1(I, J) = 0.

                   ELSE

                        B1(I, J)  = 1. + I + J

                        A1(I, J) = B1(I, J)

                   ENDIF

     10           CONTINUE

     CDVM$  PARALLEL    ( J, I )   ON   A2(I, J)

                   DO  20   J  =  1, K

                   DO  20   I  =  2, N2+1

                   IF(I.EQ.N2+1 .OR. J.EQ.1 .OR. J.EQ.K) THEN

                        A2(I, J) = 0.

                        B2(I, J) = 0.

                   ELSE

                        B2(I, J)  = 1. + ( I + N1 – 1 ) + J

                        A2(I, J) = B2(I, J)

                   ENDIF

     20           CONTINUE

                   DO  2   IT  =  1, ITMAX

     CDVM$  PREFETCH   BOUND

     C                обмен границ

     CDVM$  PARALLEL    ( J )   ON   A1(N1+1, J),

     CDVM$*    REMOTE_ACCESS  (BOUND : B2( 2, J ) )

                   DO  30   J  =  1, K

     30               A1(N1+1, J) = B2(2, J)

     CDVM$  PARALLEL    ( J )   ON   A2( 1, J),

     CDVM$*    REMOTE_ACCESS  (BOUND : B1( N1, J ) )

                   DO  40   J  =  1, K

     40               A2(1, J) = B1(N1, J)

     CDVM$  TASK_REGION  MB

     CDVM$  ON   MB( 1 )

     CDVM$  PARALLEL    ( J, I )   ON   B1(I, J),

     CDVM$*    SHADOW_RENEW ( A1 )

                   DO  50   J  =  2, K-1

                   DO  50   I  =  2, N1

     50               B1(I, J) =  (A1( I-1, J ) + A1( I, J-1 ) + A1( I+1, J) + A1( I, J+1 )) / 4

     CDVM$  PARALLEL    ( J, I )   ON   A1(I, J)

                   DO  60   J  =  2, K-1

                   DO  60   I  =  2, N1

     60               A1(I, J) =  B1( I, J )

     CDVM$  END ON

     CDVM$  ON   MB( 2 )

     CDVM$  PARALLEL    ( J, I )   ON   B2(I, J),

     CDVM$*    SHADOW_RENEW ( A2 )

                   DO  70   J  =  2, K-1

                   DO  70   I  =  2, N2

     70               B2(I, J) =  (A2( I-1, J ) + A2( I, J-1 ) + A2( I+1, J) + A2( I, J+1 )) / 4

     CDVM$  PARALLEL    ( J, I )   ON   A2(I, J)

                   DO  80   J  =  2, K-1

                   DO  80   I  =  2, N2

     80               A2(I, J) =  B2( I, J )

     CDVM$  END ON

     CDVM$  END  TASK_REGION

     2             CONTINUE

                   PRINT *, 'A1 '

                   PRINT *,  A1

                   PRINT *, 'A2 '

                   PRINT *, A2

                   END

                   SUBROUTINE  DPT( LP, HP, NT )

     C            распределение процессоров для  NT задач (NT = 2)

                   INTEGER  LP(2), HP(2)

                   NUMBER_OF_PROCESSORS( ) = 1

                   NP = NUMBER_OF_PROCESSORS( )

                   NTP = NP/NT

                   IF(NP.EQ.1) THEN

                        LP(1) = 1

                        HP(1) = 1

                        LP(2) = 1

                        HP(2) = 1

                   ELSE

                        LP(1) = 1

                        HP(1) = NTP

                        LP(2) = NTP+1

                        HP(2) = NP

                   END IF

                   END

Пример 7. Динамические задачи (цикл задач)

                   PROGRAM  MULTIBLOCK

     С            Модель многообластной задачи.

     C            Количество областей, размер каждой области, внешние и внутренние границы

     C            определяются во время выполнения программы.

     C            Тест следующих конструкций FDVM: динамические массивы,

     C            динамические задачи, асинхронный REMOTE_ACCESS  для динамических

     C            массивов (формальных параметров)

     *DVM$   PROCESSORS  MBC100( NUMBER_OF_PROCESSORS( ) )

                   PARAMETER (M = 8, N =8, NTST = 1)

     C            MXBLмаксимальное количество областей

                   PARAMETER ( MXBL=2 )

                   TYPE BLK

                   REAL, POINTER, DIMENSION (:,:) :: PA, PB

     *DVM$   ALIGN  :: PB

     *DVM$   DISTRIBUTE  :: PA

     *DVM$   DYNAMIC PA,PB

                   END TYPE BLK

                   TYPE (BLK) :: block(MXBL)

     C            block(I)%PA, block(I)%PB –

     C            значение функции на предыдущем и текущем шаге в I–ой области

     C            отложенное распределение  массивов по каждой области

                   REAL, POINTER, DIMENSION( :, : ) :: P1, P2

     *DVM$   DYNAMIC   P1, P2

     *DVM$   DISTRIBUTE :: P1

     *DVM$   ALIGN :: P2

     C            SIZE( 1:2, I) – размеры измерений I–ой области

                   INTEGER  SIZE( 2, MXBL )

     C            TINB( :,I ) – таблица внутренних границ I–ой области

     C            TINB( 1,I ) - - количество границ (от 1 до 4)

     C            TINB( 2,I ) = J  - номер смежной области

     C            TINB( 3,I ), TINB( 4,I )  - границы одномерной секции

     C            TINB( 5,I ) - номер измерения в I-ой области (1 или 2)

     C            TINB( 6,I ) - координата измерения в I-ой области

     C            TINB( 7,I ) - номер измерения в J-ой области

     C            TINB( 8,I ) - координата измерения в J-ой области

                   INTEGER  TINB( 29, MXBL )

     C            TEXB( :,I ) – таблица внешних границ I–ой области

     C            TEXB( 1,I ) - - количество границ (от 1 до 4)

     C            TEXB( 2,I ), TEXB( 3,I ) - координаты одномерной секции массива

     C                                                               для 1-ой границы

     C            TEXB( 4,I ) - номер измерения (1 или 2)

     C            TEXB( 5,I ) - координата по данному измерению

                   INTEGER  TEXB(17,MXBL)

     C            NBL -  количество областей

     C            NTSTколичество шагов

                   INTEGER  NBL, NTST

     C            IDMуказатель на свободное место динамической памяти

                   INTEGER  IDM

                   COMMON IDM

     C            массив задач

     *DVM$   TASK  TSA ( MXBL )

     C            имя группового обмена внутренних границ

     *DVM$   REMOTE_GROUP  GRINB

     C            LP( I ), HP( I ) – границы секции массива процессоров I-ой области

                   INTEGER  LP(MXBL), HP(MXBL)

     C            TGLOB( :, I ) – таблица глобальных координат в сетке алгоритма Якоби

     C                                        для I-ой области

     C            TGLOB( 1, I ) – координата по 1-му измерению

     C            TGLOB( 2, I ) – координата по 2-му измерению

                   INTEGER TGLOB(2,MXBL)

 

                   INTERFACE

                   SUBROUTINE CMPINB ( AI, AJ, N1, N2, M1, M2, S1, S2, ID, INDI, JD, INDJ)

     C            вычисление величин на внутренних границах

                   REAL, POINTER, DIMENSION(:,:) :: AI, AJ

                   END

                   SUBROUTINE  INEXB(A,B,N1,N2,S1,S2,ID,INDI)

     C            инициализация внешних границ

                   REAL, POINTER, DIMENSION(:,:) :: A,B

                   END

                   SUBROUTINE  INDOM(A,B,M,N,X1,X2)

     C            инициализация областей

                   REAL, POINTER, DIMENSION(:,:) :: A, B

                   END

                   SUBROUTINE  PRTB(B,N,M,IB)

     C            печать данных для области IB

                   REAL, POINTER, DIMENSION(:,:) :: B

                   END

                   SUBROUTINE  JACOBI(A,B,N,M)

                   REAL, POINTER, DIMENSION(:,:) :: A, B

                   END

                   END INTERFACE

 

     C            разделение области M´N на подобласти

                   CALL DISDOM(NBL,TGLOB,TEXB,TINB,SIZE,M,N,MXBL)

     C            Разделение массива процессоров по областям

                   CALL MPROC(LP,HP,SIZE,NBL)

     C            Распределение задач (областей) по процессорам.

     C            Распределение массивов по задачам

                   IDM = 1

                   DO  10  IB = 1, NBL

     *DVM$   MAP  TSA( IB )  ONTO  MBC100( LP(IB) : HP(IB) )

                   ALLOCATE (block(IB)%PA(SIZE(1, IB), SIZE(2, IB)))

                   P1 => block(IB)%PA

     *DVM$   REDISTRIBUTE  ( *, BLOCK )  ONTO  TSA( IB ) :: P1

                   ALLOCATE (block(IB)%PB(SIZE(1, IB), SIZE(2, IB)))

                   P2 => block(IB)%PB

     *DVM$   REALIGN  P2( I, J )  WITH  P1( I, J )

     10           CONTINUE

     C            Инициализация внешних границ

                   DO 20 IB=1,NBL

                   LS =0

                   DO 20 IS = 1,TEXB(1,IB)

                   CALL INEXB (block(IB)%PA, block(IB)%PB,    

                  *           SIZE(1,IB), SIZE(2,IB),

                  *           TEXB(LS+2,IB), TEXB(LS+3,IB), TEXB(LS+4,IB),

                  *       TEXB(LS+5,IB) )

                   LS = LS+4

     20           CONTINUE

     C            Инициализация областей

                   DO 25 IB = 1,NBL

                   CALL INDOM (block(IB)%PA, block(IB)%PB,    

                  *        SIZE(1,IB), SIZE(2,IB),

                  *        TGLOB(1,IB), TGLOB(2,IB))

                   LS = LS+4

     25           CONTINUE

                   DO 65  IB = 1,NBL

                   CALL PRTB(block(IB)%PA, SIZE(1,IB), SIZE(2,IB ),IB)

     65           CONTINUE

     C            Цикл итераций

                   DO  30  IT = 1, NTST

     C            упреждающая подкачка буферов для внутренних границ

     *DVM$   PREFETCH  GRINB

     C            вычисление величин на внутренних границах

                   DO  40  IB = 1, NBL

                   LS = 0

                   DO  40  IS = 1, TINB(1,IB)

                   J = TINB(LS+2, IB)

                   CALL CMPINB (block(IB)%PA, block(J)%PA,    

                 *        SIZE(1,IB), SIZE(2,IB), SIZE(1,J), SIZE(2,J),

                 *        TINB(LS+3,IB), TINB(LS+4,IB), TINB(LS+5,IB),

                 *        TINB(LS+6,IB), TINB(LS+7,IB), TINB(LS+8,IB) )

                   LS = LS+7

     40           CONTINUE

     C            вычисление величин внутри областей

     C            каждая область – отдельная задача

     *DVM$   TASK_REGION   TSA

     *DVM$   PARALLEL  ( IB )  ON  TSA( IB )

                   DO 50  IB = 1,NBL

                   CALL JACOBI(block(IB)%PA, block(IB)%PB, SIZE(1,IB), SIZE(2,IB ))

     50           CONTINUE

     *DVM$   END  TASK_REGION

                  

     30           CONTINUE

     C            конец итераций

     C            вывод значений массивов

                   DO 60  IB = 1,NBL

                   CALL PRTB(block(IB)%PA, SIZE(1,IB), SIZE(2,IB ),IB)

     60           CONTINUE

                   END

 

                   SUBROUTINE  CMPINB ( AI, AJ, N1, N2, M1, M2, S1, S2,

                *                                 ID, INDI, JD, INDJ)

     C            вычисление величин на внутренних границах

                   REAL, POINTER, DIMENSION(:,:) :: AI, AJ

                   INTEGER S1, S2

     *DVM$   INHERIT  AI, AJ

     *DVM$   REMOTE_GROUP  GRINB

                   IF ( ID .EQ. 1 )  THEN

                   IF ( JD .EQ. 1 )  THEN

     *DVM$   PARALLEL  ( K )  ON  AI( INDI, K ),

     *DVM$*    REMOTE_ACCESS (GRINB : AJ( INDJ, K ) )

                   DO 10  K = S1,S2

     10           AI(INDI,K) = AJ(INDJ,K)

                   ELSE

     *DVM$   PARALLEL  ( K )  ON  AI( INDI, K ),

     *DVM$*    REMOTE_ACCESS (GRINB : AJ( K, INDJ ) )

                   DO 20  K = S1, S2

     20           AI(INDI,K) = AJ(K,INDJ)

                   ENDIF

                   ELSE

                   IF ( JD .EQ. 1 )  THEN

     *DVM$   PARALLEL  ( K )  ON  AI( K, INDI ),

     *DVM$*    REMOTE_ACCESS (GRINB : AJ( INDJ, K ) )

                   DO 30  K = S1,S2

     30           AI(K, INDI) = AJ(INDJ,K)

                   ELSE

     *DVM$   PARALLEL  ( K )  ON  AI( K, INDI ),

     *DVM$*    REMOTE_ACCESS (GRINB : AJ( K, INDJ) )

                   DO 40  K = S1, S2

     40           AI(K,INDI) = AJ(K,INDJ)

                   ENDIF

                   ENDIF

                   END

 

                   SUBROUTINE  MPROC(LP,HP,SIZE,NBL)

     C            распределение процессоров по областям

                   INTEGER LP(NBL),HP(NBL),SIZE(2,NBL)

     C            распределение для двух областей NBL=2

                   NUMBER_OF_PROCESSORS( ) = 1

                   NP = NUMBER_OF_PROCESSORS( )

                   NPT = NP/NBL

                   IF(NP.EQ.1) THEN

                        LP(1) = 1

                        HP(1) = 1

                        LP(2) = 1

                        HP(2) = 1

                   ELSE

                        LP(1) = 1

                        HP(1) = NPT

                        LP(2) = NPT+1

                        HP(2) = NP

                   ENDIF

                   END

 

                   SUBROUTINE  INEXB(A,B,N1,N2,S1,S2,ID,INDI)

     C            инициализация внешних границ

                   REAL, POINTER, DIMENSION(:,:) :: A,B

                   INTEGER S1,S2

     *DVM$   INHERIT A,B

                   IF(ID.EQ.1)  THEN

     *DVM$   PARALLEL (K) ON A(INDI,K)

                   DO 10 K = S1,S2

                   A(INDI,K) = 0

                   B(INDI,K) = 0

     10           CONTINUE

                   ELSE

     *DVM$   PARALLEL (K) ON A(K,INDI)

                   DO 20 K = S1,S2

                   A(K,INDI) = 0

                   B(K,INDI) = 0

     20           CONTINUE        

                   ENDIF

                   END

 

                   SUBROUTINE  INDOM(A,B,M,N,X1,X2)

     C            инициализация областей

                   REAL, POINTER, DIMENSION(:,:) :: A, B

                   INTEGER X1,X2

     *DVM$   INHERIT A,B

     *DVM$   PARALLEL (I,J) ON A(I,J)

                   DO 10 I = 2,M-1

                   DO 10 J = 2,N-1

                   A(I,J) = I+J+X1+X2-3

                   B(I,J) = A(I,J)

     10           CONTINUE

                   END

 

                   SUBROUTINE  JACOBI(A,B,N,M)

                   REAL, POINTER, DIMENSION(:,:) :: A, B

     *DVM$   INHERIT A,B

     *DVM$   PARALLEL  ( I, J )  ON  B( I, J ), SHADOW_RENEW (A)

                   DO 10 I = 2,N-1

                   DO 10 J = 2,M-1

     10           B(I,J) = (A(I-1,J)+A(I+1,J)+A(I,J-1)+A(I,J+1))/4

     *DVM$   PARALLEL  ( I, J )  ON  A( I, J )       

                   DO 20 I = 2,N-1

                   DO 20 J = 2,M-1

     20           A(I,J) = B(I,J)

                   END

 

                   SUBROUTINE  PRTB(B,N,M,IB)

     C            печать данных для области IB

                   REAL, POINTER, DIMENSION(:,:) :: B

     *DVM$   INHERIT B

                   PRINT *, 'BLOCK', IB

                   PRINT *, B

                   END

 

                   SUBROUTINE DISDOM (NBL,TGL,TEXB,TINB,SIZE,M,N,MXBL)

                   INTEGER TGL(2,MXBL), TEXB(17,MXBL), TINB(29,MXBL), SIZE(2,MXBL)

                   INTEGER DM(20), DN(20),KDM,KDN,S,GM,GN

     C            разделение области M´N на две подобласти: M´(N/2) и M´(N-N/2)

                   DM(1) = M

                   KDM = 1

                   DN(1) = N/2

                   DN(2) = N - N/2

                   KDN = 2

                   S = 0

                   DO 10 I = 1,KDM

     10           S = S + DM(I)

                   IF(S.NE.M) THEN

                        PRINT *, 'wrong division M'

                        STOP

                   ENDIF

                   DO 15 IB = 1,MXBL

                   TEXB(1,IB) = 0

                   TINB(1,IB) = 0

     15           CONTINUE      

                   S = 0

                   DO 20 J = 1,KDN

     20           S = S + DN(J)

                   IF(S.NE.N) THEN

                        PRINT *, 'wrong division N'

                        STOP

                   ENDIF

                   DM(1) = DM(1) - 1

                   DN(1) = DN(1) - 1

                   DM(KDM) = DM(KDM) - 1

                   DN(KDN) = DN(KDN) - 1

     C            генерация таблиц (графов) внешних и внутренних границ

                   IB = 1

                   GM = 2

                   GN = 2

                   DO 30 J = 1,KDN

                   DO 40 I = 1,KDM

                   IF (I.EQ.1) THEN

                        L = TEXB(1,IB)*4

                        TEXB(L+2,IB) = 1

                        TEXB(L+3,IB) = DN(J)+2

                        TEXB(L+4,IB) = 1 

                        TEXB(L+5,IB) = 1

                        TEXB(1,IB) = TEXB(1,IB)+1

                   ELSE

                        L = TINB(1,IB)*7

                        TINB(L+2,IB) = IB-1

                        TINB(L+3,IB) = 1

                        TINB(L+4,IB) = DN(J)+2

                        TINB(L+5,IB) = 1

                        TINB(L+6,IB) = 1

                        TINB(L+7,IB) = 1

                        TINB(L+8,IB) = DM(I-1)+1

                        TINB(1,IB) = TINB(1,IB)+1

                   ENDIF

                   IF (I.EQ.KDM) THEN

                        L = TEXB(1,IB)*4

                        TEXB(L+2,IB) = 1

                        TEXB(L+3,IB) = DN(J)+2

                        TEXB(L+4,IB) = 1 

                        TEXB(L+5,IB) = DM(I)+2

                        TEXB(1,IB) = TEXB(1,IB)+1

                   ELSE

                        L = TINB(1,IB)*7

                        TINB(2,IB) = IB+1

                        TINB(3,IB) = 1

                        TINB(4,IB) = DN(J)+2

                        TINB(5,IB) = 1

                        TINB(6,IB) = DM(I)+2

                        TINB(7,IB) = 1

                        TINB(8,IB) = 2

                        TINB(1,IB) = TINB(1,IB)+1

                   ENDIF

                   IF (J.EQ.1) THEN

                        L = TEXB(1,IB)*4

                        TEXB(L+2,IB) = 1

                        TEXB(L+3,IB) = DM(I)+2

                        TEXB(L+4,IB) = 2 

                        TEXB(L+5,IB) = 1

                        TEXB(1,IB) = TEXB(1,IB)+1

                   ELSE

                        L = TINB(1,IB)*7

                        TINB(L+2,IB) = IB-KDM

                        TINB(L+3,IB) = 1

                        TINB(L+4,IB) = DM(I)+2           

                        TINB(L+5,IB) = 2

                        TINB(L+6,IB) = 1

                       

Приложение 3. Распределение динамических массивов в программе на языке FDVM 2.0 (Фортран 77)

П3.1. Динамические массивы в программе на языке Фортран 77

Отсутствие средств работы с динамическими массивами в языке Фортран 77 заставляет пользователей моделировать динамическую память с помощью так называемых рабочих массивов. Динамическая память описывается как одномерный массив большого размера. Динамические массивы разной формы определяются как непрерывные сегменты в этом рабочем массиве.

Пример 1. Использование рабочего массива.

                   REAL HEAP(100000)

                   READ (6 , *)   NM

     C            в программе требуются динамические массивы размера N´ N и M´ M

                   CALL SUB1(HEAP(1), N, HEAP(1+N*N), M)

                   END

 

                   SUBROUTINE SUB1(A, N, B, M)

                   DIMENSION  A(N , N),  B(M , M)

                   .      .      .

                   END

Анализ существующих программ показал отсутствие определенной дисциплины работы с моделируемыми динамическими массивами. В частности, отсутствует явная фиксация размещения массива в памяти. Обращение к динамическому массиву осуществляется ссылкой на рабочий массив. Это делает невозможным для компилятора определить форму массива.

П3.2. Динамические массивы в модели FDVM 2.0. Директива POINTER

Предлагаемая модель является подмножеством модели динамических массивов Фортран 90 и позволяет без изменений выполнять эту модель в трех средах программирования

Для динамических массивов, распределяемых по умолчанию, FDVM разрешает использовать любые способы моделирования динамической памяти. Для динамических массивов, распределяемых директивами DISTRIBUTE и ALIGN, FDVM определяет следующую дисциплину размещения и использования динамических массивов.

*      Все явно распределяемые динамические массивы размещаются в пуле динамической памяти с именем HEAP

REAL  HEAP (MAXM)

где MAXM - количество слов динамической памяти.

*      Тип данных и количество измерений динамического массива фиксируется следующей директивой FDVM

 

 

pointer-directive

is  type ,  POINTER  ( dimension-list ) :: pointer-name-list

 

dimension

is    :

 

pointer-name

is    scalar-int-variable-name

 

or   int-array-name

type определяет тип данных динамического массива. Переменные, специфицированные директивой POINTER, имеют следующие ограничения.

*      Размеры каждого измерения и размещение динамического массива в HEAP фиксируется следующим оператором

                   pointer = ALLOCATE ( sdim ,... )

где

pointer -

ссылка на целочисленную переменную (скаляр или элемент массива) с атрибутом POINTER

sdim     -

целочисленный одномерный массив размера ndim. ndim - количество измерений многомерного массива, размещаемого в динамической памяти HEAP. Значение sdim( i ) определяет размер i-ого измерения. Размер выделяемого сегмента равен sdim( 1 )´ sdim( 2 )´....´ sdim( ndim ).

Целочисленная функция ALLOCATE выдает номер начального элемента выделяемого сегмента динамической памяти HEAP. Функция ALLOCATE программируется пользователем, поэтому она может иметь дополнительные параметры помимо обязательного параметра sdim.

*      В процедуре, где производится размещение динамического массива, разрешается только следующий тип ссылки на динамический массив

HEAP( pointer )

При этом такая ссылка может быть только фактическим аргументом вызова функции или подпрограммы.

Пусть в программе используется несколько пулов динамической памяти с идентификаторами ID1 , …, IDn. Нет необходимости переписывать программу с одним пулом динамической памяти HEAP. Достаточно указать следующую спецификацию

     CDVM$  HEAP ID1 , …, IDn

Но каждый пул IDi должен удовлетворять вышеуказанным требованиям пула HEAP.

Пул может содержать только массивы, распределяемые директивами DISTRIBUTE и ALIGN.

П3.3. Директива DISTRIBUTE и REDISTRIBUTE для динамических массивов

Для распределения динамических массивов используются директивы DISTRIBUTE и REDISTRIBUTE, синтаксис которых расширен следующим образом:

distribute

is   .  .  .

 

or  pointer-name

Если в качестве distributee указан скаляр или массив с атрибутом POINTER , то распределение откладывается до выполнения функции ALLOCATE, которая присваивает значение данному указателю. Вместо функции ALLOCATE выполняется создание массива и его распределение по форматам директивы DISTRIBUTE.

Директива REDISTRIBUTE для динамического массива может выполняться только после выполнения функции ALLOCATE, которая присваивает значение соответствующей переменной POINTER.

Если указатель динамического массива является элементом массива указателей, то распределить динамический массив можно только директивой REDISTRIBUTE. Т.к. директива REDISTRIBUTE допускает лишь ссылку на имя указателя, то элемент массива указателей необходимо предварительно переслать в скалярную переменную-указатель. Распределить массив с указателем PT(I) можно с помощью следующей последовательности операторов:

                   P1 = PT( I )

      CDVM$  REDISTRIBUTE P1( BLOCK, BLOCK )

Программу, приведенную в примере 1, необходимо трансформировать в следующую FDVM программу.

Пример 2. Распределение динамических массивов FDVM.

                   REAL  HEAP(100000)

                   INTEGER  ALLOCATE

     CDVM$  REAL, POINTER ( : , : )  ::  PA, PB

                   INTEGER  PAPB

     C            дескрипторы динамических массивов

                   INTEGER  DESCA(2),  DESCB(2)

     CDVM$  DISTRIBUTE (BLOCK , BLOCK) ::  PA, PB

     C            в программе требуются массивы размера N´ N и M´ M

                   READ (6 , *)   NM

     C            конфигурация первого массива

                   DESCA(1) = N

                   DESCA(2) = N

     C            размещение и распределение первого массива

                   PA = ALLOCATE (DESCA,1)

     C            конфигурация второго массива

                   DESCB(1) = M

                   DESCB(2) = M

     C            размещение и распределение второго массива

                   PB = ALLOCATE ( DESCB, N*N+1 )

                   CALL SUB1(HEAP(PA), N, HEAP(PB), M)

                   END

 

                   SUBROUTINE SUB1(A, N, B, M)

                   DIMENSION  A(N , N),  B(M , M)

     CDVM$  DISTRIBUTE *(BLOCK , BLOCK) ::  A, B

                   .      .      .

                   END

 

                   FUNCTION  ALLOCATE(DESC, P)

                   INTEGER  DESC(2), P

                   ALLOCATE = P

                   END

П3.4. Выравнивание динамических массивов

Для спецификации выравнивания динамических массивов синтаксис директив ALIGN и REALIGN расширен следующим образом.

alignee

is    .   .   .

 

or   pointer-name

 

align-target

is    .   .   .

 

or    pointer-name

Если в директиве ALIGN в качестве выравниваемого массива (alignee) указана переменная с атрибутом POINTER, то выполнение директивы откладывается до выполнения функции ALLOCATE, которая определяет значение этой переменной. Директива REALIGN может выполняться только после выполнения функции ALLOCATE.

Пример 3. Выравнивание динамических массивов.

                   REAL  HEAP(100000)

     CDVM$  REAL, POINTER ( :, : ) :: PX, PY

                   INTEGER  PX, PY, DESC(2)

     CDVM$  ALIGN  PY( I, J )  WITH  PX( I, J )

     CDVM$  DISTRIBUTE  PX ( BLOCK, BLOCK )

                   .   .   .

                   PX = ALLOCATE(DESC, ...)

                   PY = ALLOCATE(DESC, ...)

                   .   .   .

     CDVM$  REDISTRIBUTE  PX ( BLOCK, * )

Пусть задана цепочка выравниваний директивами ALIGN

P1  f1  P2  f2  .   .   .  fN-1  PN

где  fi - функция выравнивания,

      Pi - указатель на динамический массив.

Тогда размещение динамических массивов (выполнение функции ALLOCATE) должно происходить в обратном порядке, т.е.

PN = ALLOCATE(...)

.   .   .

P2 = ALLOCATE(...)

P1 = ALLOCATE(...)

Если указатель динамического массива является элементом массива указателей, то выравнивание динамического массива можно выполнить только директивой REALIGN. Т.к. директива REALIGN допускает лишь ссылку на имя указателя, то элемент массива указателей необходимо предварительно переслать в скалярную переменную-указатель. Выравнивание массива с указателем PT(I) на массив с указателем PT(J)  можно выполнить с помощью следующей последовательности операторов:

                   P1 = PT( I )

                   P2 = PT( J )

      CDVM$  REALIGN  P1( I, J )  WITH  P2( I+1, J )

Другие примеры распределения динамических массивов см. в следующем разделе.

П3.5. Фрагмент динамической многообластной задачи

Рассмотрим фрагмент программы, которая динамически настраивается на количество областей и размеры каждой области.

     С            NA - максимальное количество областей

                   PARAMETER ( NA=20 )

     CDVM$  PROCESSORS  R( NUMBER_OF_PROCESSORS( ) )

     С            память для динамических массивов

                   REAL  HEAP(100000)

     С            размеры динамических массивов

                   INTEGER  SIZE( 2, NA )

     С            массивы указателей для А и В

     CDVM$  REAL, POINTER ( :, : ) :: PA, PB, P1, P2

                   INTEGER   P1, P2, PA(NA), PB(NA)

     CDVM$  TASK  PT ( NA )

     CDVM$  ALIGN  :: PB, P2

     CDVM$  DISTRIBUTE  :: PA, P1

                   .   .   .

                   NP = NUMBER_OF_PROCESSORS( )

     С            распределение массивов по задачам

     С            динамическое размещение массивов и выполнение отложенных директив

     С            DISTRIBUTE и ALIGN

                   IP = 1

                   DO  20  I = 1, NA

     CDVM$  MAP  PT( I )  ONTO  R( IP : IP+1 )

                   PA(I) = ALLOCATE ( SIZE(1,I), HEAP )

                   P1 = PA(I)

     CDVM$  REDISTRIBUTE  ( *, BLOCK )  ONTO  PT( I ) :: P1

                   PB(I) = ALLOCATE ( SIZE(1,I), HEAP )

                   P2 = PB(I)

     CDVM$  REALIGN  P2( I, J )  WITH  P1( I, J )

                   IP = IP + 2

                   IF( IP .GT. NP )  THEN  IP = 1

     20           CONTINUE

                   .   .   .

     С            распределение вычислений по задачам

     CDVM$  TASK_REGION   PT

     CDVM$  PARALLEL  ( I )  ON  PT( I )

                   DO 50  I = 1,NA

                        CALL JACOBY( HEAP(PA(I)), HEAP(PB(I)), SIZE(1, I), SIZE(2, I) )

     50           CONTINUE

     CDVM$  END  TASK_REGION

Массивы (области) циклически распределяются на секции из 2-х процессоров. Если NA > NP/2 , то на некоторые секции будет распределено несколько массивов. Витки циклов, распределенные на одну секцию, будут выполняться последовательно в модели параллелизма по данным.

Приложение 4. Асинхронное копирование на языке FDVM 2.0

Асинхронное копирование позволяет совместить передачу данных между процессорами с выполнением других операторов.

Асинхронное копирование определяется комбинацией директивы начала копирования (ASYNCHRONOUS  ID) и директивой ожидания окончания копирования (ASYNCWAIT  ID). Соответствие директив определяется одним идентификатором ID.

П4.1. Директива ASYNCID

Директива ASYNCID описывает отдельный идентификатор для каждой пары директив асинхронного копирования.

Синтаксис директивы:

asyncid-directive

is   ASYNCID async-name-list

 

 

П4.2. Директива F90

Директива F90 представляет собой оператор копирования с префиксом.

Синтаксис.

f90-directive

is    F90   copy-statement

 

 

copy-statement

is    array-section  = array-section

 

 

array-section

is   array-name  [( section-subscript-list )]

 

 

section-subscript

is   subscript

 

or  subscript-triplet

 

 

subscript-triplet

is   [ subscript ] : [ subscript ] [ : stride]

 

 

subscript

is   int-expr

 

 

stride

is   int-expr

П4.3. Директивы ASYNCHRONOUS и END ASYNCHRONOUS

Директивы ASYNCHRONOUS и END ASYNCHRONOUS задают блочную конструкцию.

Синтаксис.

asynchronous-construct

is   asynchronous-directive

 

                    f90-directive

                  [ f90-directive ] …

                    copy-loop

                   [ copy-loop ] …

 

    end-asynchronous-directive

 

 

asynchronous-directive

is   ASYNCHRONOUS async-name

 

 

end-asynchronous-directive

is   END ASYNCHRONOUS

Все операторы присваивания в циклах копирования (copy-loop) должны быть описаны директивами F90 с соответствующим оператором копирования.

П4.4. Директива ASYNCWAIT

Синтаксис.

asyncwait-directive

is    ASYNCWAIT async-name

Пример из раздела 6.3.4.1 можно специфицировать как асинхронное копирование на языке FDVM 2.0 следующим образом.

     CDVM$  ASYNCID  TR

                   REAL A(N1,N2,N3), B(N1,N3)

                        .   .   .

     CDVM$  ASYNCHRONOUS  TR

     CDVM$  F90 A( :, 5, 3:N3 )     = B( :, 1:N3-2 )

                   DO  10  I1 = 1, N1

                   DO  10  I2 = 2, N3-1

     10               A(I1, 5, I2+1)     = B(I1, I2-1)

     CDVM$  END ASYNCHRONOUS

                        .   .   .

                   последовательность операторов,

                   которая выполняется на фоне передачи данных

                        .   .   .

     CDVM$  ASYNCWAIT  TR

 


Fortran-DVM - оглавление Часть 1(1-4) Часть 2 (5-6) Часть 3 (7-15) Часть 4
(Приложения)