12 WIDTH * 1.D0/INTRVL
13 SUM * 0.D0
14 DO 100 1С « 9MYNUM, INTRVL,
0NUMPR0CS
15 SUM « SUM + WIDTH * F( (1С - 0.5D0) * WIDTH )y
16 100
CONTINUE
17 T * DFNA(SUMALL, SUM)
18 CALL FCLOC(TIME)
В строках 12-13 инициализируются интервалы, на которые разбивается
интервал интегрирования, и локальные (для процессов) суммы. Цикл DO 100 -пример
предпланируемого цикла DO. Если программа выполняется одним процессором, это
идентично последовательной программе. Если же 0NUMPR0C больше 1, каждый процесс
выполняет вычисления в своем интервале, равном 1/0NUMPROC. Первоначально была
идея проверить, насколько эффективно программа векторизуется, поэтому она была
откомпилирована с опцией векторизации, а затем выполнялась одним процессором (т.
е. последовательно). Результат интегрирования накапливался в SUM (строка 15).
Этот цикл и вычисления были помечены в листинге исходного текста, выдаваемом
компилятором VS FORTRAN как векторизуемые.
После накопления статистики о
времени выполнения последовательной программы, была накоплена статистика о
времени выполнения параллельной программы на нескольких прогонах с различным
числом процессов (2 или 4) и разбиением интервала интегрирования на 10 000, 1000
000 и 10 000 ООО интервалов.
После предпланированных выполнений программы
вычисления числа Пи то же самое было сделано в режиме самопланирования. Эта
самопланирующаяся версия программы идентична предпланированной версии, за
исключением цикла D0 100, который заменяется на:
14 9D0 100 1С - lf INTRVLf
CHUNK « nnnn
15 SUM - SUM + WIDTH * F( (1С - 0.5D0) * WIDTH )y
16 100
9ENDD0 N0WAIT
17 T " DFNA(SUMALL, SUM)
Цикл D0 ... END DO является параллельной формой обычного
последовательного цикла D0, определяемой следующим образом: когда процесс
достигает начала цикла, он запрашивает работу, определяемую значением индекса
цикла. После получения этого значения он выполняет тело цикла для этого значения
индекса и снова запрашивает работу. При этом, вообще говоря, последовательные
итерации цикла должны быть независимыми. Дополнительные сведения DO и
других параллельных конструкциях, поддерживаемых ЕРЕХ, можно найти в приложении
Е4.
Здесь нет конфликтов по доступу к переменной, так как каждый процесс
накапливает сумму в своей локальной переменной. Для большей эффективности можно
применить в цикле ООО дополнительную конструкцию CHUNK с тем, чтобы при
запросе работы назначать процессу последовательность значений индекса, а не одно
значение. Так как в описываемом тесте действия, выполняемые при одной итерации
цикла, очень малы, были проведены эксперименты с разными размерами
последовательности значений в предположении, что больший размер
последовательности уменьшает накладные расходы на синхронизацию и распределения
значений индекса между процессами. Опция NO WAIT в предложении END D0 строки 16
определяет, что после завершения своей части работы в цикле процесс продолжает
выполнение, не дожидаясь, пока другие процессы закончат свою работу, даже если
эти процессы продолжают выполнение предложений до начала цикла или в теле цикла.
Во многих приложениях выполнение предложений, следующих за циклом, зависит от
результатов полного выполнения цикла, поэтому каждый процесс должен дождаться
выполнения цикла всеми остальными процессами, но в данном случае это не
так.
Вызов параллельной библиотечной процедуры DFNA в строке 17 обеспечивает
синхронизованное суммирование в переменной SUMALL частичных результатов каждого
процесса, полученных в локальных переменных SUM. DFNA является библиотечной
процедурой, выполняющей суммирование, при аппаратной синхронизации процессов.
При этом гарантируется, что в данный момент времени это суммирование выполняет
только один процесс. Это, конечно, важно и необходимо, так как результат
выполнения двумя процессами записи в одну ячейку памяти в лучшем случае
непредсказуем. Вызов FCL0C обеспечивает запись времени завершения выполнения
программы.