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

5. Распределение вычислений

5.1. Параллельные циклы

5.1.1. Определение параллельного цикла

Моделью выполнения FDVM программы, как и программ на других языках с параллелизмом по данным, является модель ОПМД (одна программа - множество потоков данных). На все процессоры загружается одна и та же программа, но каждый процессор в соответствии с правилом собственных вычислений выполняет только те операторы присваивания, которые изменяют значения переменных, размещенных на данном процессоре (собственных переменных).

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

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

Цикл, удовлетворяющий этим условиям, будем называть параллельным циклом. Управляющая переменная последовательного цикла, охватывающего параллельный цикл или вложенного в него, может индексировать только локальные (размноженные) измерения распределенных массивов.

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 ]

Директива PARALLEL размещается перед заголовком цикла и распределяет витки циклов в соответствии с распределением массива или шаблона. Семантика директивы аналогична семантике директивы ALIGN, где индексное пространство выравниваемого массива заменяется индексным пространством цикла. Индексы циклов в списке do-variable-list перечисляются в том порядке, в котором размещены соответствующие операторы DO в тесно-гнездовом цикле.

Синтаксис и семантика отдельных частей директивы описаны в следующих разделах:

new-clause                      раздел 5.1.3

reduction-clause             раздел 5.1.4

shadow-renew-clause      раздел 6.2.2

shadow-compute-clause  раздел 6.2.3

across-clause                  раздел 6.2.4

remote-access-clause      раздел 6.3.1

consistent-clause             раздел 8

 Пример 5.1. Распределение витков цикла с регулярными вычислениями.

                   REAL  A(N, M),  B(N, M+1),  C(N, M),  D(N, M)

     CDVM$  ALIGN  ( I, J )  WITH  B( I, J+1 ) :: A, C, D

     CDVM$  DISTRIBUTE B ( BLOCK , BLOCK )

                   .   .   .

     CDVM$  PARALLEL  ( I, J )  ON  B( I, J+1 )

                   DO  10  I = 1, N

                   DO  10  J = 1, M-1

                        A(I,J)     = D(I,J) + C(I,J)

                        B(I,J+1) = D(I,J) - C(I,J)

     10           CONTINUE

Цикл удовлетворяет всем условиям параллельного цикла. В частности, левые части операторов присваивания одного витка цикла A(I,J) и B(I,J+1) размещаются на одном процессоре через выравнивание массивов А и В.

Если левые части операторов присваивания размещены на разных процессорах (распределенный виток цикла), то цикл необходимо разделить на несколько циклов.

Пример 5.2. Разделение цикла 

 

CDVM$  PARALLEL  ( I )  ON  A( 2*I )

     DO  10  I = 1, N

                 DO  10  I = 1, N

       A(2*I) = .   .   .

  10                 A(2*I) = .   .   .

       B(3*I) = .   .   .

CDVM$  PARALLEL  ( I)  ON  B( 3*I )

10 CONTINUE

                 DO  11  I = 1, N

 

  11                 B(3*I) = .   .   .

Цикл разделен на 2 цикла, каждый из которых удовлетворяет условию параллельного цикла.

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

Если использование переменной локализовано в пределах одного витка цикла, то ее необходимо указать в спецификации NEW

new-clause

is    NEW   new-variable-list  )

 

new-variable

is     array-name

 

or    scalar-variable-name

 NEW-переменные (приватные переменные) не могут быть распределенными массивами. Значение приватной переменной не определено в начале витка цикла и не используется после витка цикла, поэтому в каждом витке цикла может использоваться свой экземпляр приватной переменной.

Пример 5.3. Спецификация приватной переменной.

     CDVM$  PARALLEL  ( I, JON  A( I, J ) , NEW ( X )

                   DO  10  I = 1, N

                   DO  10  J = 1, N

                        X = B(I,J) + C(I,J)

                        A(I,J) = X

     10           CONTINUE

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

Очень часто в программе встречаются циклы, в которых выполняются редукционные операции - в некоторой переменной суммируются элементы массива или вычисляется максимальное (минимальное) значение. Витки таких циклов можно распределять, если указать спецификацию 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

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

Введем следующие обозначения

rv

- редукционная переменная-скаляр или
  элемент редукционной переменной-массива

L

- одномерный массив целого типа

n

- число координат минимума или максимума

er

- выражение, не содержащее rv

Ik

- целая переменная

op

- одна из следующих операций языка Фортран: +, -, .OR., .AND., .EQV., .NEQV.

ol

- одна из следующих операций языка Фортран: .GE., .GT., .LE., .LT.

f

- функция max или min

В теле цикла редукционный оператор имеет один из следующих видов:

1)  rv = rv  op  er

     rv = er  op  rv 

 

2)  rv = f( rv, er )

     rv = f( er, rv ) 

 

3)  if( rv  ol  er )   rv = er

     if( er  ol  rv )   rv = er 

 

4)  if( rv  ol  er )  then

       rv = er

       L( 1 ) = e1

         .  .   .

       L( n ) = en

    endif

    if( er  ol  rv )  then

       rv = er

       L( 1 ) = e1

        .  .  .

       L( n ) = en

    endif

Соответствие вида оператора, операции языка Фортран и имени редукции FDVM приведено в следующей таблице. 

Вид оператора

операция Фортран

имя редукции FDVM

 

 

 

1

+

            SUM(rv)

1

*

            PRODUCT(rv)

1

.AND.

            AND(rv)

1

.OR.

            OR(rv)

1

.EQV.

            EQV(rv)

1

.NEQV.

            NEQV(rv)

2,3

 

            MAX(rv)

2,3

 

            MIN(rv)

4

 

            MINLOC(rv, L, n)

4

 

            MAXLOC(rv, L, n)

Операция MAXLOC (MINLOC) предполагает вычисление максимального (минимального) значения и определение его координат.

Пример 5.4. Спецификация редукции.

                   S = 0

                   Y =1.E10

                   X = -1.

                   IMIN(1) = 0

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

     CDVM$*     REDUCTION(SUM(S), MAX(X), MINLOC(Y,IMIN,1))

                   DO  10  I = 1, N

                        S = S + A(I)

                        X = MAX(X, A(I))

                        IF(A(I) .LT. Y) THEN

                                   Y = A(I)

                                   IMIN(1) = I

                        ENDIF

     10           CONTINUE

5.2. Вычисления вне параллельного цикла

Вычисления вне параллельного цикла выполняются по правилу собственных вычислений. Пусть оператор

IF   p   THEN   lh = rh

где   p  – логическое выражение,

lh – левая часть оператора присваивания (ссылка на скаляр или элемент массива),

rh – правая часть оператора присваивания (выражение),

находится вне параллельного цикла.

Тогда этот оператор будет выполняться на процессоре, где распределены данные со ссылкой lh (процессор own( lh )). Все данные в выражениях p и rh должны быть размещены на процессоре own( lh ). Если какие-либо данные из выражений p и rh отсутствуют на процессоре own( lh ), то их необходимо указать в директиве удаленного доступа (см. 6.1.2) перед этим оператором.

Если lh является ссылкой на распределенный массив А и существует зависимость по данным между rh и lh, то распределенный массив необходимо размножить с помощью директивы

REDISTRIBUTE А( *,...,* )  или  REALIGN А( *,...,* )

перед выполнением оператора.

Пример 5.5. Оператор собственных вычислений.

                   PARAMETER  (N = 100)

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

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

     CDVM$  DISTRIBUTE  ( BLOCK, * ) :: A

                   .   .   .

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

     C            собственные вычисления вне циклов

     С           

     С            оператор собственных вычислений

     С            левая и правая части – на одном процессоре

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

                   DO  10  J = N-1, 1, -1

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

                   DO  20  I = 1, J

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

     20           CONTINUE

     C            собственные вычисления в последовательном цикле,

     С            охватывающем параллельный цикл

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

     10           CONTINUE

Отметим, что A(J,N+1) и A(J,J) локализованы на том процессоре, где размещается X(J).

6.  Cпецификация удаленных данных

6.1. Определение удаленных ссылок

Удаленными данными будем называть данные, размещенные на одном процессоре и используемые на другом процессоре. Фактически эти данные являются общими (разделяемыми) данными для этих процессоров. Ссылки на такие данные будем называть удаленными ссылками. Рассмотрим обобщенный оператор

IF (…A(inda)…)      B(indb) = …C(indc)

где   A, B, C - распределенные массивы,

inda, indb, indc - индексные выражения.

В модели DVM этот оператор будет выполняться на процессоре own(B(indb)), т.е. на том процессоре, где размещен элемент B(indb). Ссылка A(inda) и C(indc) не являются удаленными ссылками, если соответствующие им элементы массивов A и C размещены на процессоре own(B(indb)). Единственной гарантией этого является выравнивание A(inda), B(indb) и C(indc) в одну точку шаблона выравнивания. Если выравнивание невозможно или невыполнено, то ссылки A(inda) и/или C(indc) необходимо специфицировать как удаленные ссылки. В случае многомерных массивов данное правило применяется к каждому распределенному измерению.

По степени эффективности обработки удаленные ссылки разделены на два типа: SHADOW и REMOTE.

Если массивы B и C выровнены и

inda = indc ± d  ( d – положительная целочисленная константа),

то удаленная ссылка C(indc) принадлежит типу SHADOW. Удаленная ссылка на многомерный массив принадлежит типу SHADOW, если распределяемые измерения удовлетворяют определению типа SHADOW.

Удаленные ссылки, не принадлежащие типу SHADOW, составляют множество ссылок типа REMOTE.

Особым множеством удаленных ссылок являются ссылки на редукционные переменные (см. 5.1.4), которые принадлежат типу REDUCTION. Эти ссылки могут использоваться только в параллельном цикле.

Для всех типов удаленных ссылок возможны два вида спецификаций: синхронная и асинхронная.

Синхронная спецификация задает групповую обработку всех удаленных ссылок для данного оператора или цикла. На время этой обработки, требующей межпроцессорных обменов, выполнение данного оператора или цикла приостанавливается. Асинхронная спецификация позволяет совместить вычисления с межпроцессорными обменами. Она объединяет удаленные ссылки нескольких операторов и циклов. Для запуска операции обработки  ссылок и ожидания ее завершения служат специальные директивы. Между этими директивами могут выполняться другие вычисления, в которых отсутствуют ссылки на специфицированные переменные.

6.2. Удаленные ссылки типа SHADOW

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

Удаленная ссылка типа SHADOW означает, что обработка удаленных данных будет происходить через “теневые” грани. Теневая грань представляет собой буфер, который является непрерывным продолжением локальной секции массива в памяти процессора (см. рис.6.1.).Рассмотрим оператор

A( i ) = B( i + d2) + B( id1)

где d1, d2 – целые положительные константы. Если обе ссылки на массив B являются удаленными ссылками типа SHADOW, то массив B необходимо специфицировать в директиве SHADOW как B( d1 : d2 ), где d1 – ширина левой грани, а d2 – ширина правой грани. Для многомерных массивов необходимо специфицировать грани по каждому измерению. При спецификации теневых граней указывается максимальная ширина по всем удаленным ссылкам типа SHADOW.

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

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

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

Задание размера теневых граней как width эквивалентно заданию width : width.

По умолчанию, распределенный массив имеет теневые грани шириной 1 с обеих сторон каждого распределенного измерения.

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

Синхронная спецификация является частью директивы PARALLEL

shadow-renew-clause

is   SHADOW_RENEW   ( renewee‑list )

 

renewee

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

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

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

Пример 6.1. Спецификация SHADOW-ссылок без угловых элементов.

                   REAL  A(100),  B(100)

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

     CDVM$  DISTRIBUTE  ( BLOCK) :: A

     CDVM$  SHADOW  B( 1:2 )

                   .   .   .

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

                   DO  10  I = 2, 98

                        A(I) = (B(I-1) + B(I+1) + B(I+2) ) / 3

     10           CONTINUE

При обновлении значений в теневых гранях используются максимальные размеры 1:2 , заданные в директиве SHADOW.

Распределение и схема обновления теневых граней показана на рис.6.1.

Рис.6.1. Распределение массива с теневыми гранями.

На каждом процессоре распределяются два буфера, которые являются непрерывным продолжением локальной секции массива. Левая теневая грань имеет размер в 1 элемент (для B(I-1)), правая теневая грань имеет размер в 2 элемента (для B(I+1) и B(I+2)). Если перед выполнением цикла произвести обмен между процессорами по схеме на рис.6.1., то цикл может выполняться на каждом процессоре без замены ссылок на массивы ссылками на буфер.

Для многомерных распределенных массивов теневые грани могут распределяться по каждому измерению. Особая ситуация возникает, когда необходимо обновлять "угол" теневых граней. В этом случае требуется указать дополнительный параметр CORNER.

Пример 6.2. Спецификация SHADOW-ссылок с угловыми элементами.

                   REAL  A(100,100),  B(100,100)

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

     CDVM$  DISTRIBUTE  A ( BLOCK,BLOCK)

                   .   .   .

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

                   DO  10  I = 2, 99

                   DO  10  J = 2, 99

                        A(I,J) = (B(I,J+1) + B(I+1,J) + B(I+1,J+1) ) / 3

     10           CONTINUE

Теневые грани для массива В распределяются по умолчанию размером в 1 элемент по каждому измерению. Т.к. имеется удаленная "угловая" ссылка B(I+1,J+1) , то указывается параметр CORNER.

Рис.6.2. Распределение массива с теневыми гранями.

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

В разделах 6.2.1 и 6.2.2. были описаны способы обновления значений в теневых гранях путем обмена данными между процессорами. При этом новые значения массива вычислялись в одном цикле, а обновление производилось либо перед выполнением, либо во время выполнения другого цикла.

При некоторых условиях значения в теневых гранях можно обновлять без обмена данными между процессорами. Новые значения в теневых гранях можно вычислять в том же цикле, в котором вычисляются новые значения массивов. Такой способ обновления значений в теневых гранях описывается спецификацией SHADOW_COMPUTE, которая является частью директивы PARALLEL.

Рассмотрим некоторый параллельный цикл

     CDVM$  PARALLEL (I1 , I2, …, InON  A(f1,f2 ,…,fk)

где A – идентификатор массива, в соответствии с которым распределяются витки цикла.

Пусть

{LH} - множество ссылок на распределенные массивы в левых частях операторов присваивания цикла;

{RH} - множество ссылок на распределенные массивы в правых частях (выражениях) операторов присваивания цикла.

Для применения спецификации SHADOW_COMPUTE необходимо выполнение следующих условий:

Во время выполнения цикла значения в теневых гранях массивов из множества {LH} обновляются. Ширина обновленной части каждой теневой грани равна ширине соответствующей теневой грани массива A.

Пример 6.3. Спецификация SHADOW_COMPUTE.

     CDVM$  DISTRIBUTE (BLOCK) :: A, B, C, D

     CDVM$  SHADOW  A(1:2)

     CDVM$  SHADOW  B(2:2)

     CDVM$  PARALLEL ( I )  ON  C( I ),  SHADOW_COMPUTE,

     CDVM$*                                                         SHADOW_RENEW( A, B )

                   DO 10  I = 1, N

                        C( I ) = A( I ) + B( I )

                        D( I ) = A( I ) - B( I )

     10           CONTINUE

Так как по умолчанию ширина теневых граней для массивов C и D равна 1, то условие 1) удовлетворяется. Выполнение спецификации SHADOW_RENEW удовлетворяет условие 2).

Cинтаксис спецификации SHADOW_COMPUTE директивы PARALLEL:  

shadow-compute-clause

is   SHADOW_COMPUTE [( dist-array-name

                                                   ( shadow-edge-list ) )]

Разрешено задание размеров теневых граней. Если требуется обновить значения не во всех теневых гранях или не всю теневую грань целиком, тогда следует задать размер обновляемых граней с помощью shadow-edge-list.

Пример 6.4. Метод переменных направлений.

                   real A(N,N), C(N,N)

     CDVM$  DISTRIBUTE A(BLOCK,BLOCK)

     CDVM$  ALIGN (I,J)  WITH  A(I,J) :: C

     C    по направлению X

     CDVM$  PARALLEL (J,I)  ON  A(I,J), SHADOW_COMPUTE (A(1:1, 0:0))

                   DO  J=1,N

                   DO  I=1,N

                          A(I,J)=….

                   ENDDO

                   ENDDO

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

                   DO  J=2,N-1

                   DO  I=2,N-1

                         C(I,J)=f(A(I-1,J),A(I+1,J))

                   ENDDO

                   ENDDO

     C   по направлению Y

     CDVM$  PARALLEL (J,I)  ON  A(I,J), SHADOW_COMPUTE (A(0:0,1:1))

                   DO  J=1,N

                   DO  I=1,N

                         A(I,J)=….

                   ENDDO

                   ENDDO

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

                   DO  J=2,N-1

                   DO  I=2,N-1

                        C(I,J)=f(A(I,J-1),A(I,J+1))

                   ENDDO

                   ENDDO

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

Рассмотрим следующий цикл

                   DO  10  I = 2, N-1

                   DO  10  J = 2, N-1

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

     10           CONTINUE

Между витками цикла с индексами i1 и  i2  ( i1<i2 ) существует зависимость по данным (информационная связь) массива A, если оба эти витка осуществляют обращение к одному элементу массива по схеме запись‑чтение или чтение‑запись.

Если виток i1  записывает значение, а виток i2 читает это значение, то между этими витками существует потоковая зависимость или просто зависимость i1® i2.

Если виток i1 читает “старое” значение, а виток  i2 записывает “новое” значение, то между этими витками существует обратная зависимость  i1¬ i2.

В обоих случаях виток i2 может выполняться только после витка i1.

Значение i2 - i1 называется диапазоном или длиной зависимости. Если для любого витка i существует зависимый виток i + d (d - константа), тогда зависимость называется регулярной или зависимостью с постоянной длиной.

Цикл с регулярными вычислениями, в котором существуют регулярные зависимости по распределенным массивам, можно распределять с помощью директивы PARALLEL, указывая спецификацию ACROSS. 

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 )

В спецификации ACROSS перечисляются все распределенные массивы, по которым существует регулярная зависимость по данным. Для каждого измерения массива указывается длина прямой зависимости (flow-dep-length) и длина обратной зависимости (anti-dep-length). Нулевое значение длины зависимости означает отсутствие зависимости по данным.

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

Если в цикле обновляются не все значения массива, а только значения некоторых секций массива, то эти секции следует указать в разделе SECTION.

Пример 6.5. Спецификация цикла с регулярной зависимостью по данным.

     CDVM$  PARALLEL  ( I, J )  ON  A( I, J ) , ACROSS ( A( 1:1, 1:1 ))

                   DO  10  I = 2, N-1

                   DO  10  J = 2, N-1

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

     10           CONTINUE

По каждому измерению массива А существует прямая и обратная зависимость длиной 1.

Спецификация ACROSS реализуется через теневые грани. Длина обратной зависимости определяет ширину обновления правой грани, а длина прямой зависимости – ширину обновления левой грани. Обновление значений правых граней производится перед выполнением цикла (как для директивы SHADOW_RENEW). Обновление левых граней производится во время выполнения цикла по мере вычисления значений удаленных данных. Фактически, ACROSS-ссылки являются подмножеством SHADOW–ссылок, между которыми существует зависимость по данным.

Эффективность параллельного выполнения цикла ACROSS

Измерение массива, по которому существует зависимость по данным, будем называть рекуррентным измерением.

Степень эффективности параллельного выполнения цикла ACROSS зависит от количества распределенных рекуррентных измерений.

Одномерный массив. Для одномерного распределенного массива с рекуррентным измерением возможно только последовательное выполнение (см. рис. 6.3).

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

1) Cуществует хотя бы одно не рекуррентное измерение. Массив и цикл распределяются только по этому измерению. Цикл выполняется как обычный параллельный цикл без спецификации ACROSS.

Пример 6.6. Распараллеливание по не рекуррентному измерению.

     CDVM$  DISTRIBUTE  A( BLOCK, * )

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

                   DO  30  I = 1,N1

                   DO  30  J = 2,N2-1

     30               A(I,J)     = A(I,J-1) + A(I,J+1)

Отметим, что этот способ может быть не самым эффективным, если N1 значительно меньше N2 и количества процессоров (недостаточный параллелизм)

 2) Распределено только одно рекуррентное измерение. Остальные измерения локализованы на каждом процессоре. Система поддержки организует конвейерное распараллеливание (см. рис.6.4). При этом размер ступени конвейера автоматически определяется на каждой ЭВМ, в зависимости от времени выполнения цикла и времени передачи данных при обновлении теневых граней.

Пример 6.7. Конвейерное распараллеливание.

     CDVM$  DISTRIBUTE  A( BLOCK, * )

     CDVM$  PARALLEL  ( I, J )  ON  A( I, J ) ,  ACROSS ( A( 1:1, 1:1 ))

                   DO  40  I = 2,N1-1

                   DO  40  J = 2,N2-1

     40               A(I,J)     = A(I,J-1) + A(I,J+1) + A(I-1,J) + A(I+1,J)

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

 3) Существует m>1 распределенных рекуррентных измерений. Массив виртуальных процессоров содержит также m измерений. Система поддержки автоматически организует параллельное выполнение по гиперплоскостям массива процессоров. Каждая гиперплоскость имеет m-1 измерение.

Пример 6.8. Распараллеливание по гиперплоскостям.

     CDVM$  DISTRIBUTE  A( BLOCK, BLOCK )

     CDVM$  PARALLEL  ( I, J )  ON  A( I, J ) ,  ACROSS ( A( 1:1, 1:1 ))

                   DO  50  I = 2,N1-1

                   DO  50  J = 2,N2-1

     50               A(I,J)     = A(I,J-1) + A(I,J+1) + A(I-1,J) + A(I+1,J)

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

Рис.6.3. Последовательное выполнение

Рис.6.4. Конвейерное выполнение

Рис.6.5. Распараллеливание по гиперплоскостям
             решетки виртуальных процессоров.

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

Обновление значений в теневых гранях, описанное в разделе 6.2.2, является неделимой (синхронной) операцией обмена для неименованной группы распределенных массивов. Эту операцию можно разделить на две операции:

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

Асинхронное обновление теневых граней для именованной группы распределенных массивов описывается следующими директивами.

 Определение группы. 

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

Директива SHADOW_START должна выполняться после директивы SHADOW_GROUP. После выполнения директивы SHADOW_GROUP директивы SHADOW_START и SHADOW_WAIT могут выполняться многократно. Новые значения в теневых гранях могут использоваться только после выполнения директивы SHADOW_WAIT.

Особым вариантом является использование директив SHADOW_START и SHADOW_WAIT в спецификации shadow-renew-clause параллельного цикла.

Синтаксис спецификации shadow-renew-clause расширен следующим образом: 

shadow-renew-clause

is     .   .   .

 

or   shadow-start-directive

 

or   shadow-wait-directive

Если в спецификации указана директива SHADOW_START, то на каждом процессоре производится опережающее вычисление значений, пересылаемых в теневые грани других процессоров. После этого производится обновление теневых граней и вычисление на внутренней области локальной секции массива (см. рис.6.2.).

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

Пример 6.9. Совмещение счета и обновления теневых граней.

                    REAL  A(100,100),  B(100,100),  C(100,100),  D(100,100)

     CDVM$  ALIGN  ( I, J )  WITH  C( I, J ) :: A, B, D

     CDVM$  DISTRIBUTE  ( BLOCK, BLOCK ) :: C

                   .   .   .

     CDVM$  SHADOW_GROUP  AB ( A, B )

                   .   .   .

     CDVM$  SHADOW_START  AB

                   .   .   .

     CDVM$  PARALLEL  ( I, J )  ON  C ( I, J ),  SHADOW_WAIT  AB

                   DO  10  I = 2, 99

                   DO  10  J = 2, 99

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

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

     10           CONTINUE

Распределенные массивы по умолчанию имеют теневые грани в 1 элемент по каждому измерению. Т.к. в спецификации параллельного цикла указана директива SHADOW_WAIT, то изменяется порядок выполнения витков цикла. Сначала будут выполняться вычисления на внутренней области каждой локальной секции массива, затем выполнится директива ожидания новых значений теневых граней. Выполнение цикла завершается вычислением значений пересылаемых в теневые грани. 

6.3. Удаленные ссылки типа REMOTE

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

Удаленные ссылки типа REMOTE специфицируются директивой 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

Директива REMOTE_ACCESS может быть отдельной директивой (область действия - следующий оператор) или дополнительной спецификацией в директиве PARALLEL (область действия – тело параллельного цикла).

Если удаленная ссылка задается как имя массива без списка индексов, то все ссылки на этот массив в параллельном цикле (операторе) являются  удаленными ссылками типа REMOTE.

Рассмотрим удаленную ссылку на многомерный распределенный массив

A( ind1, ind2,…,indk )

Пусть indj – индексное выражение по j-ому измерению.

В директиве REMOTE_ACCESS индексное выражение указывается без изменений, если

Во всех остальных случаях в директиве REMOTE_ACCESS вместо indj указывается “:” (все измерение).

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

Если в директиве REMOTE_ACCESS не указано имя группы (remote-group-name), то выполнение такой директивы происходит в синхронном режиме. В пределах нижестоящего оператора или параллельного цикла компилятор заменяет все вхождения удаленной ссылки ссылкой на буфер. Пересылка удаленных данных производится перед выполнением оператора или цикла.

Пример 6.10. Синхронная спецификация  удаленных ссылок типа REMOTE.

                   DIMENSION  A(100,100),  B(100,100)

     CDVM$  DISTRIBUTE (*,BLOCK)  :: A

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

                   .   .    .

     CDVM$  REMOTE_ACCESS  ( A(50,50) )

     С            замена ссылки A(50,50) ссылкой на буфер

     С            рассылка значения A(50,50) по всем процессорам

     1             X = A(50,50)

                   .   .   .

     CDVM$  REMOTE_ACCESS  ( B(100,100) )

     С            пересылка значения В(100,100) в буфер процессора own(A(1,1)

     2             A(1,1) = B(100,100)

                   .   .   .

     CDVM$  PARALLEL  (I,J)  ON  A(I,J) ,  REMOTE_ACCESS  ( B(:,N) )

     С            рассылка значений B(:,N) по процессорам own(A(:,J))

     3             DO 10  I = 1, 100

                   DO 10  J = 1, 100

     10           A(I,J) = B(I,J) + B(I,N)

Первые две директивы REMOTE_ACCESS специфицируют удаленные ссылки для отдельных операторов. REMOTE_ACCESS в параллельном цикле специфицирует удаленные данные (столбец матрицы) для  всех процессоров, на которые распределен массив А.

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

Если в директиве REMOTE_ACCESS указано имя группы (remote-group-name), то выполнение директивы происходит в асинхронном режиме. Для спецификации этого режима необходимы следующие дополнительные директивы.

 Описание имени группы. 

remote-group-directive

is    REMOTE_GROUP  remote-group-name-list

Идентификатор, определенный этой директивой, может использоваться только в директивах REMOTE_ACCESS , PREFETCH и RESET. Группа remote-group представляет собой глобальный объект, областью действия которого является вся программа.

prefetch-directive

is   PREFETCH  remote-group-name

 

 

reset-directive

is    RESET  remote-group-name

 Рассмотрим следующую типовую последовательность асинхронной спецификации удаленных ссылок типа REMOTE.

     CDVM$  REMOTE_GROUP  RS

     10           .   .   .

     CDVM$  PREFETCH  RS

                   .   .   .

     C            вычисления, в которых не участвуют удаленные ссылки r1 , …,rn

                   .   .   .

     CDVM$  PARALLEL  .  .  .  ,  REMOTE_ACCESS  (RS : r1)

                   .   .   .

     CDVM$  REMOTE_ACCESS  (RS : ri)

                   .   .   .

     CDVM$  PARALLEL  .  .  .  ,  REMOTE_ACCESS  (RS : rn)

                   .   .   .

                   IF( P ) GO TO 10

При первом прохождении указанной последовательности операторов директива PREFETCH не выполняется. Директивы REMOTE_ACCESS выполняется в обычном синхронном режиме. При этом происходит накопление ссылок в переменной RS. После выполнения всей последовательности директив REMOTE_ACCESS значение переменной RS равно объединению подгрупп удаленных ссылок ri È ...È rn.

При втором и последующих прохождениях директива PREFETCH осуществляет упреждающую пересылку удаленных данных для всех ссылок, составляющих значение переменной RS. После директивы PREFETCH и до первой директивы REMOTE_ACCESS с тем же именем группы можно выполнять другие вычисления, которые перекрывают ожидание обработки удаленных ссылок. При этом директивы REMOTE_ACCESS никакой пересылки данных уже не вызывают.

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

Если характеристики группы удаленных ссылок изменились, то необходимо присвоить неопределенное значение группе удаленных ссылок с помощью директивы RESET, после чего будет происходить новое накопление группы удаленных ссылок.

Рассмотрим следующий фрагмент многообластной задачи. Область моделирования разделена на 3 подобласти, как показано на рис.6.6.

 

Рис.6.6. Разделение области моделирования. 

Пример 6.11. Использование  группы регулярных удаленных ссылок.

                   REAL  A1(M,N1+1),  A2(M1+1,N2+1),  A3(M2+1,N2+1)

     CDVM$  DISTRIBUTE   ( BLOCK,BLOCK) :: A1, A2, A3

     CDVM$  REMOTE_GROUP  RS

                   DO  1  ITER = 1, MIT

                   .   .   .

     C            обмен границами по линии раздела D

     CDVM$  PREFETCH   RS

                   .   .   .

     CDVM$  PARALLEL  ( I )  ON  A1 ( I, N1+1 ),  REMOTE_ACCESS ( RS: A2(I,2))

                   DO  10  I = 1, M1

     10               A1(I,N1+1) = A2(I,2)

     CDVM$  PARALLEL  ( I )  ON  A1 ( I, N1+1 ),  REMOTE_ACCESS ( RS: A3(I-M1,2))

                   DO  20  I = M1+1, M

     20               A1(I,N1+1) = A3(I-M1,2)

     CDVM$  PARALLEL  ( I )  ON  A2 ( I, 1 ),  REMOTE_ACCESS ( RS: A1(I,N1))

                   DO  30  I = 1, M1

     30               A2(I,1) = A1(I,N1)

     CDVM$  PARALLEL  ( I )  ON  A3 ( I, 1 ),  REMOTE_ACCESS ( RS: A1(I+M1,N1))

                   DO  40  I = 1, M2

     40               A3(I,1) = A1(I+M1,N1)

                   .   .   .

                   IF (NOBLN)   THEN

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

                   .   .   .

     CDVM$  RESET  RS

                   END IF

                   .   .   .

     1             CONTINUE

6.3.4. Асинхронное копирование по ссылкам типа REMOTE

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

6.3.4.1. Цикл и операторы копирования

Рассмотрим следующий цикл

                   DO  10  I1 = L1,H1,S1

                        .   .   .

                   DO  10  In = Ln,Hn,Sn

      10                    A(f1,…,fk) = B (g1,…,gm)

где A, B - идентификаторы разных распределенных массивов.

Li,Hi,Si – инварианты цикла

fi = ai *Ii + bi

gj = cj *Ij + dj

ai, bi , cj, dj – целые выражения, инварианты цикла (выражения, значения которых не изменяются в процессе выполнения цикла).

Каждая переменная цикла Il может быть использована не более чем в одном выражении fi и не более чем в одном выражении gj.

Цикл может содержать несколько операторов, удовлетворяющих вышеуказанным ограничениям. Такой цикл будем называть циклом копирования (copy-loop).

Цикл копирования может быть описан одним или несколькими операторами присваивания вида: секция-массива = секция-массива. Такие операторы будем называть  операторами копирования (copy-statement).

Для цикла копирования 10 оператор копирования определяется следующим образом

                        A(a1,…,ak) = B(b1,…,bm)

где ai, bj являются триплетами

ai = (ai *Li + bi) : (ai *Hi + bi) : (ai *Si)

bj = (cj *Lj + dj) : (cj *Hj + dj ) : (cj *Sj)

Рассмотрим следующий цикл копирования

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

                   DO  10  I1 = 1, N1

                   DO  10  I2 = 2, N3-1

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

Этому циклу соответствует следующий оператор копирования

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

 6.3.4.2. Директивы асинхронного копирования

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

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

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

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

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

asyncid-directive

is   ASYNCID async-name-list

 

 

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

Директивы 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.3.4.1 можно специфицировать как асинхронное копирование следующим образом.

     CDVM$  ASYNCID  TR

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

                        .   .   .

     CDVM$  ASYNCHRONOUS  TR

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

     CDVM$  END ASYNCHRONOUS

                        .   .   .

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

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

                        .   .   .

     CDVM$  ASYNCWAIT  TR

6.4. Удаленные ссылки типа REDUCTION

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

Если спецификация REDUCTION в параллельном цикле указана без имени группы, то она является синхронной спецификацией и выполняется следующим образом.

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

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

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

Асинхронная спецификация позволяет:

Для асинхронной спецификации, кроме директивы 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

 Типовая последовательность директив асинхронной спецификации типа REDUCTION выглядит следующим образом.

      CDVM$  REDUCTION_GROUP  RD

                   .   .   .

     CDVM$  PARALLEL  .  .  .  ,  REDUCTION  (RD : d1)

     C            локальная редукция d1

                   .   .   .

     CDVM$  PARALLEL  .  .  .  ,  REDUCTION  (RD : dn)

     C            локальная редукция dn

                   .   .   .

     CDVM$  REDUCTION_START  RD

     C            начало глобальной редукции di È ...È dn

                   .   .   .

     CDVM$  REDUCTION_WAIT  RD

     C            конец глобальной редукции di È ...È dn

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

Пример 6.12. Асинхронная спецификация типа REDUCTION.

      CDVM$  DISTRIBUTE  A ( BLOCK )

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

      CDVM$  REDUCTION_GROUP  RD

                   .   .   .

                   S = 0.

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

      CDVM$*      REDUCTION ( RD : SUM(S))

                   DO  10  I = 1, N

     10               S = S + A(I)

                        X = 0.

     CDVM$  PARALLEL  ( I )  ON  B( I ),

      CDVM$*      REDUCTION ( RD : MAX(X))

                   DO  20  I = 1, N

     20               X = MAX(X, ABS( B(I) ) )

 

      CDVM$  REDUCTION_START  RD

     C            начало глобальной редукции SUM(S) и MAX(X)

     CDVM$  PARALLEL  ( I )  ON  A( I )

                   DO  30  I = 1, N

     30               A(I) = A(I) + B(I)

      CDVM$  REDUCTION_WAIT  RD

     C            конец глобальной редукции

                   PRINT *, S, X

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


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