Различие скалярных и векторных конструкций
Поскольку forall не цикл, а перечисление параллельных процессов, то напрашивающаяся аналогия с циклом ограниченна.
В ряде случаев операторы do и forall одинаковы по действию. Тривиальный пример:
Integer, dimension(1:4) :: A
A=0 ! параллельные действия
forall (i=1:4) ! параллельные действия
A(i)=0
End forall
doi=1,4 ! последовательные действия
A(i)=0
End do
Простой пример, из книги Немнюгина, иллюстрирующий разницу между do и forall
1. Используется оператор Do
integer,dimension(1:4):: A=(/ 1,2,3,4 /)
Do i=2,3 ! последовательные действия
A(i) = A(i-1) + A(i) + A(i+1)
Enddo
Получим
A(2) = A( 1) + A(2) + A(3)=1+2+3=6
A(3) = A( 2) + A(3) + A(4)=6+3+4=13 ! A( 2)=6 - изменившееся значение
2. Оператор forall, перечисляющий параллельные процессы над исходными значениями массива, – те же по виду действия дают другой ответ
forall (i=2:3 ) ! параллельные действия
A(i)=A(i-1)+A(i)+A(i+1) !подставляется значение A( 2)=2
! то же по-другому A(i)=sum(A(i-1:i+1)) - проясняет суть дела
End forall
Получим
A(2) = A( 1) + A2) + A(3)=1+2+3=6
A(3) = A( 2) + A(3) + A(4)=2+3+4=9 ! A( 2)=2 исходное значение
A(2:3) = (/ sum(A(1:3)) , sum(A(2:4)) - всё разъясняет: берем старые значения, а заносим новые значения A
и ни к чему здесь forall -это чисто академический стиль
Нетрудно заметить внешнее сходство Do - цикл и forall -как бы цикл по параллельным процессам. Не проходит аналогия forall с циклом foreach из языка PHP.
Есть кардинальное отличиецикла и перечисления параллельных процессовforall:
- doзадает последовательность действий, которые выполняются над скалярами либо целиком векторами;
- forall задает параллельные действия, которые выполняются над компонентами векторов, матриц, многомерных массивов, секциями с непременным требованием конформности условия и действий;
- doработает с текущими значениями массивов, а forall как бы работает с двойной памятью - использует стартовые значения массивов, а формирует новые значения.
Парафлоид – один оператор вместо двадцати
В этом разделе показан более сложный пример вычисления парафлоида -квадратной матрицы минимальных расстояний между вершинами ориентированного графа с взвешенными дугами. Граф задан квадратной матрицей инцидентности. Строки и столбцы матрицы соответствуют вершинам графа. Инцидентные дуги соответствуют положительным компонентам матрицы. Схематично показано вычисление меры близости вершин графа по методу Флойда.
Таблица 29.
Пример вычисления парафлоида в операторе forall
A | J | |
i | parafloid(i,j) = minval( A(i,:)+A(:,j) ) | A(i,:)- строка i |
A(:,j)- столбец j |
С целью упрощения на схеме не показаны условия положительной определенности, дополнительно прописанные в оператореforall.
Парафлоид - единственный выполняемый оператор
program parafloida
Implicit none
integer,parameter:: N=10
! A - взвешенная входная матрица инцидентности
integer,dimension(1:n,1:n) :: A=1, parafloid
! парафлоид parafloid - выходная матрица мин. расстояний
integer i,j
forall( i=1:n, j=1:n, i/=j ) &
parafloid(i,j) = minval( A(i,:)+A(:,j), &
mask = A(i,:)>0 .and. A(:,j)>0 )
write(6,1) (parafloid(i,:),i=1,n)
1 format(1x,<n>i3)
end program parafloida
Попробуйте написать программу paraseqva с помощью традиционных конструкций – и Вы увидите, что она будет на порядок сложнее: вместо одного оператора - программа из 20 операторов.
program paraseqva ! взвешенная входная матрица инцидентности
Implicit none
integer,parameter:: N=10
integer,dimension(1:n,1:n) :: A=1, parafloid
! парафлоид - выходная матрица мин. расстояний
integer i,j
integer,dimension(1:n) :: str,stlb, summa
integer parafloidMin,i1
open(6,file='parafloid.txt')
do i=1,N
A(i,i)=0
Enddo
do i=1,N
do j=1,N
if(i/=j) then
parafloidMin = huge(0) ! #7fffffff
do i1=1,N
str=A(i,i1); stlb=A(i1,j); summa(i1)=str(i1)+stlb(i1)
Enddo
do i1=1,N
if(str(i1)==0 .or. stlb(i1)==0) cycle
if(summa(i1)<parafloidMin) parafloidMin = summa(i1)
Enddo
parafloid(i,j) = parafloidMin
Else
parafloid(i,j) = 0
Endif
Enddo
Enddo
write(6,1) (parafloid(i,:),i=1,N)
1 format(1x,<N>i3)
end program paraseqva
Пример парафлоида – многогранный:
- A(i,:)- i-ая строка и A(:,j)- j-ый столбец заданы секциями двумерного массива, образующими векторы;
- конформные векторы A(i,:)иA(:,j)- суммируются A(i,:)+A(:,j), образуя новый вектор положительно определенных крестообразных сумм;
- из сумм выбирается минимум при помощи итоговой функции minVal, формируя элемент парафлоида;
- forall задаёт перебор в пространстве секции, совпадающей с положительно определёнными недиагональными элементами матрицы;
- данныйforall имеет объём вычислений, пропорциональный O (N3).
Дата добавления: 2016-02-13; просмотров: 1000;