Оператор и конструкция forall

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

АналогичноDo Whileконструкцияforallуправляет блоком операторов, но в отличие от Do Whileуправляющая маска векторная, в общем случае многомерная, а не скалярная. Действиянадкомпонентами секции выполняются параллельно и независимо.

Триплеты, указывающие законы изменения индексов в секции, и маску для секции задают

- в простом безблочном операторе

forall(индексИимярек=триплет, ..[, маска_секции])единственный_простой_конформный

- или в составном одноблочном операторе
forall (индексИмярек=триплет, .. &
индексИмярек=триплет [, скалярная_маска_секции] )
! маскированные действия, конформные секции, построенной
! по всем возможным комбинациям индексов из триплетов
end forall

Сначала рассмотрим четыре варианта решения простой задачи. На этих решениях покажем разницу в понимании do и forall.

Пример: найти diaPro – произведение ненулевых элементов главной диагонали.

1. Правильное решение с традиционными конструкциямиdo иif

real,dimension(1:10,1:10) :: A

real diaPro; integer i

diaPro =1

do i=1,10

if( A(i,i)/=0) diaPro = diaPro* A(i,i)

Enddo

2. Заменив do на forall, получим неправильное решение

real,dimension(1:10,1:10) :: A

realDiapro; integer i

Diapro =1

Forall(i=1:10, A(i,i)/=0) Diapro = Diapro* A(i,i)

Допущена ошибка в левой части оператора Diapro = diapro* A(i,i)–этоприсваивание,неконформное заголовку оператора Forall: diaPro–скаляр,в то время как A(i,i) определено врамках секции1:10.

3. Правильное решение с использованием оператораforall

real,dimension(1:10,1:10) :: A

real,dimension(1:10) :: Diagonal

realdiaPro; integeri

Diagonal =1;

forall (i=1:10, A(i,i)/=0)Diagonal(i)= A(i,i)

diaPro= product(Diagonal)

4. Нет решения с помощьюоператораwhere

Уforall есть аналоги:

- where- оба задают работу с многомерным объектом;

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

- do-и в теле оператора forall элементы массивов адресуются по индексам, заданным в заголовке forall.

Однако смысл адресации элементов массива в doи в forall абсолютно разный:

- в doэлементы массива выбираются последовательно по мере изменения индексов;

- в forall элементы массива выбираются независимо-параллельно, по предварительно построенным всем возможным комбинациям индексов, порядок обработки в языке не фиксирован:

Таким образом do- основа последовательного выполнения повторяющихся действий; forall - основа параллельного выполнения повторяющихся действий.

Любое присваивание массивов и where можно переписать как forall, но некоторые forall не могут быть записаны только на уровне манипуляций с массивами в where:

- например, через forall легко записать: where (A /= 0.0) B=1.0/A - сами напишите;

- однако, следующий пример forall нельзя записать на уровне манипуляций с массивами

forall (i=1:n, j=1:n) H(i,j) = 1.0/(i+j-1)

- этот оператор устанавливает элемент массива H(i, j) равным значению 1.0/ (i + j - 1) для любых пар значений i и j между 1 и n.

Forall задает:

- список имен индексов, варьируемых в секции;

- каждому поименованному индексу сопоставлен триплет, определяющий закон его изменения;

- после списка задается необязательная маска, конформная секции, которая записывается в терминах варьируемых индексов;

- над какими компонентами массивов, какие именно действия и в какой последовательности - задается в блоке оператора forall;

- порядок обработки компонент в языке не фиксирован.

Порядок действий, соответствующих forall:

- по заданным триплетам создаются списки всех возможных значений индексов;

- далее формируются все комбинации индексов;

- по комбинациям индексов формируется секция и конформная ей маска;

- затем независимо и параллельно выполняются конформные действия в последовательности заданной в блоке;

- действия выполняются только для истинных значений конформной им маски.

Получается, что это не цикл, а перечисление потенциально параллельных процессов. Синтаксис записи триплетов в forall через двоеточие ещё раз подчёркивает:

- уместность аналогии с секциями, а не циклами;

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

- чтобы потенциально параллельная конструкция стала реально таковой, необходимы два условия:

1. распараллеливающий компилятор, как IFC;

2. наличие многих процессоров.

Наши рекомендации