В.А.Фисун 13.03.97 Язык Фортран GNS для систем с распределенной памятью Рекомендации по использованию языка О Г Л А В Л Е Н И Е 1. Введение........................................... 1 2. Тип данных - TASKID............................... 3 3. Задачи и процессы.................................. 5 3.1. Создание процессов.............................. 6 3.2. Завершение процессов и завершение программы..... 9 3.3. Ввод-вывод.....................................10 4. Передача сообщений................................11 4.1. Способы передачи сообщений.....................11 4.2. Идентификация абонентов.........................13 4.3. Операторы передачи сообщения.................. 15 5. Конструкция выбора............................... 21 6. Стандартные процедуры............................. 22 7. Функции редукции.................................. 26 7.1. Использование функций редукции................. 27 7.2. Использование статической модели паралеллизма.. 28 8. Литература........................................ 31 1. Введение Данное руководство есть модификация описания Фортран GNS [1], языка программирования для вычислительных систем с распределенной па- мятью, дополненное комментариями об особенностях использования парал- лельных конструкций языка. Фортран GNS представляет собой расширение языка Фортран 77 средс- твами для образования параллельных процессов и обмена сообщениями меж- ду ними. За основу расширений приняты средства, предложенные в проекте стандарта, которые разработаны в Германии в рамках европейской прог- раммы ESPRIT. В общем случае, программа на языке Фортран GNS состоит из описа- ния одной начальной задачи (главной программной единицы), и описания одной или нескольких других задач (программные единицы нового для Фортрана 77 вида). Вычислительные процессы, порожденные по описаниям задач, выполняются параллельно и взаимодействут между собой при помощи аппарата передачи сообщений. - 2 - Выполнение программы начинается с выполнения главного процесса, образованного по описанию начальной задачи. Он порождает другие про- цессы, которые сразу же начинают выполняться и, в свою очередь, могут также порождать новые процессы. По одному описанию программной единицы-задачи может создаваться произвольное количество процессов. Так как процессу доступны только свои локальные данные, то процессы, образованные по одному образцу, могут приобретать индивидуальность, принимая информацию от других про- цессов и от каналов ввода. Обмен информацией между процессами (переда- ча констант, скаляров и массивов всех определенных в языке типов) осу- ществляется с помощью операторов передачи сообщений. Предусмотрено три способа передачи сообщений: синхронный, асинхронный и "без ожидания". Каждый процесс имеет "почтовый ящик" для буферизации поступающих сооб- щений. При порождении процессов должны быть заданы номера виртуальных "процессоров", на которых должны "выполняться" процессы, причем допус- кается размещение на одном процессоре несколько процессов. Средства отображения номеров виртуальных вычислителей на конфигурацию реальной вычислительной платформы не включены в язык,они оговариваются в инс- трукциях по запуску программ на конкретных установках. При этом требу- ется задать соответствие между номерами (именами) реальных процессоров платформы и виртуальными номерами, а, иногда, и уточниться именами за- дач, размещаемых на этих процессорах. Сложность реализации динамической загрузки задач при параллельной работе на архитектуре МРР, наличие, как правило, при запуске программы информации об дислокации задач на процессорах, философия SPMD програм- мирования (одна программа - много данных) привели к введению в рамках языка Фортран GNS "статической модели" параллелизма. В этой схеме порождение и запуск всех параллельных задач програм- мы - процессов производится одновременно при запуске программы. При этом, все задачи имеют равный статус (нет главной, дерева последова- тельности порождений процессов). Процедура порождения задач, функции определения имен главного, порождающего процесса теряют смысл. Завер- шение программы может быть произведено из любого процесса. Понятие но- мера виртуального процессора становится основным средством отображе- ния: физический процессор -> виртуальные процессоры -> имена задач. На одном виртуальном процессоре может быть размешена только одна задача, но на одном физическом - несколько виртуальных. - 3 - Одновременно в язык вводятся средства - встроенные процедуры для определения топологии вычислительной платформы, имен, состава и дисло- кацию вычислительных процессов программы, механизм завершения програм- мы. Используя эти средства любой процесс может проводить настройку на реальную вычислительную среду. Статическая и динамическая модели па- раллелизма сосуществуют в рамках одного языка: для каждого случая сле- дует использовать соответствующие функции. Реализация языка Fortran GNS может быть проведена на базе штатного компилятора Фортран 77, входящего в состав программного обеспечения вычислительной системы,и библиотеки системной поддержки для интерпре- тации параллельных конструкций языка. При этом тексты на языке Fortran GNS отображаются в тексты на языке Фортран 77, содержащие обращения к программам библиотеки поддержки. Одним из вариантов такого отображения является описание языка Фортран МВК [3]. Преобразование текстов прог- рамм может производиться вручную или с помощью разработанного для это- го конвертора Fortran GNS -> Фортран МВК. 2. Тип данных - TASKID По семантике языка Fortran GNS все процессы программы получают уникальные имена - системные идентификаторы, по которым производится отождествление корреспондентов при обмене сообщениями между процессами и в терминах которых задается среда выполнения функций редукции. Эти имена вырабатываются функцией порождения процессов - встроенной функ- цией языка NEWTASK. Структура системного идентификатора определяется реализацией, это имя не имеет внешнего представления. Для манипулирования именами процессов внутри программы в язык Fortran GNS вводится новый для Фортрана тип данных - тип TASKID. Зна- чения этого типа представляют собой имена процессов, которые вырабаты- ваются функцией порождения процессов. При статической модели параллелизма системные идентификаторы про- цессов вырабатываются системой запуска программы и могут быть получены пользователем встроенными функциями. Добавляется константа .NOTASKID., которая представляет собой "ну- левое" значение для объектов этого типа. Данные типа TASKID должны быть описаны в операторе TASKID, син- таксис которого аналогичен синтаксису операторов объявления типа в Фортране 77. Данные этого типа могут использоваться в операторах EQUI- VALENCE, но при этом могут быть эквивалентными только данным типа TAS- - 4 - KID. Допускается использование TASKID в качестве описателя типа подп- рограммы-функции. Использование переменных данного типа в операторах СOMMON огова- ривается в инструкциях по использованию языка на конкретных установ- ках, в них же приводятся размеры имени процесса для расчетов длин об- щих блоков. В реализации на базе Фортран МВК [3] допускается использо- вание данных типа TASKID в общих блоках, их длина - одно слово (как у данных типа INTEGER). Для данных типа TASKID определены следующие операции: операции .EQ. , .NE. и присваивание (когда операнды операций,левая и правая части операторов присваивания имеют тип TASKID). Данные типа TASKID используются в операторах передачи/приема со- общений - SEND и RECEIVE для задания абонентов - получателя или отпра- вителя . Такие данные могут также передаваться в качестве параметров процедурам и функциям, а также могут быть переданы другим процессам с помощью операторов передачи сообщений. Значения типа TASKID не могут использоваться в списках ввода-вы- вода, так как не имеют внешнего представления. Начальная инициализация переменных этого типа также, как и других переменных Фортрана, не предусматривается, поэтому использование дан- ных до присваивания им значений некорректно. Присвоение начальных зна- чений зтим данным в операторах DATA не предусмотрено. Спецификация данных типа TASKID в виде массива, структура которого совпадает с конфигурацией вычислительной системы, облегчает программи- рование задачи, например, может унифицировать операторы передачи дан- ных между соседними процессами. В языке есть возможность заданием идентификатора массива данных типа TASKID указать массовую операцию для всех его элементов: в функциях порождения процессов,редукции и операциях передачи сообщений. Такая запись может ускорить выполнение программы, так как такие массовые операции могут выполняться парал- лельно. Для задания массовых операций над частью массива - подмассива можно присвоить подмассиву имя оператором EQUIVALENCE, динамическое формирование структур подмассивов можно производить операторами языка Фортран МВК. Например: TASKID T1(100),T2(100),TM DIMENSION TM(100,2) EQUIVALENCE (TM(1,1),T1(1)),(TM(1,2),T2(1)) - 5 - При статической модели параллелизма инициализация данных этого типа производится функциями преобразования номеров виртуальных процессоров в имена задач. 3. Задачи и процессы В языке вводится дополнительный вид программных единиц - прог- раммные единицы-задачи. Программа может содержать (помимо традиционных для Фортрана программных единиц) одну или более программных единиц-за- дач. Главная программная единица (main program) определяет главный и единственный - начальной процесс программы.Эта единица может иметь за- головок: PROGRAM  1n 0, где  1n  0- имя программы. По Фортрану, заголовок программы может отсутствовать. Имя программы (MAIN при его отсутствии) идентифицирует главную программную единицу программы, ссылки на него невозможны. (Конкретные реализации могут разрешать использование этого имени в операторах пе- редачи сообщений в качестве адресата.) При запуске начального процесса ему присваивается другое имя - системный идентификатор, по которому на него могут ссылаться другие процессы программы при передаче сообщений или при выполнении функций редукции. Это имя может быть получено любым процессом при помощи встроенной функцией MASTER без параметров. Результат функции имеет тип TASKID. Программная единица-задача являются описанием задачи. Вычисли- тельные процессы создаются по описанию задачи динамически и во время создания им присваиваются уникальные имена - системные идентификаторы. По одному описанию задачи может быть образовано произвольное число процессов данного класса. Первым оператором программной единицы-задачи является оператор заголовка, имеющий вид: TASK PROGRAM  1n 0, где  1n 0 - имя программной едини- цы-задачи. В остальном, структура программной единицы-задачи не отличается от структуры главной программной единицы Фортрана 77. В частности, последним оператором, как обычно, является оператор END. Задачи не могут иметь общей памяти с другими задачами, в частнос- ти, с главной, поэтому общие блоки (COMMON-блоки) задач локальны в пределах каждой задачи и программных единицах, которые в ней использу- ются. Семантика COMMON-блоков в пределах одной задачи - традиционная. - 6 - 3.1. Создание процессов. Для создания процессов в динамической модели параллелизма исполь- зуется стандартная функция NEWTASK. Обращение к этой функции произво- дится операторами присваивания вида:  1i 0t = NEWTASK ( 1n 0,  1ia 0) , где  1n 0 - имя программной единицы-задачи;  1ia  2-  0константа, имя переменной, элемента массива или массива цело- го типа; значения этого параметра определяют виртуальные но- мера вычислителей, на которых создаются порождаемые процессы.  1i 0t  2-  0имя переменной, элемента массива или массива типа TASKID, ку- да заносятся имена (системные идентификаторы) порожденных процессов. Функция NEWTASK создает по описанию задачи с именем  1n  0вычислитель- ные процессы, количество которых определяется числом виртуальных номе- ров вычислителей. Это число равно количеству элементов массива пара- метра  1ia 0 или равно одному для скалярного параметра. Результатом выполнения функции NEWTASK является имя процесса или массив имен (системных идентификаторов) созданных процессов. Эти имена присваиваются переменным  1i 0t. Если  1n  0не совпадает с именем программной единицы-задачи, по кото- рой образован текущий процесс, то оно должно быть описано. По аналогии с оператором EXTERNAL, для описания имен внешних задач вводится опера- тор спецификации TASK EXTERNAL, имеющий вид: TASK EXTERNAL  1n  0[,  1n 0i ]... где  1n 0,  1n 0i - имена программных единиц-задач. Имена, указанные в списке этого оператора, разрешается использо- вать в качестве фактических параметров процедур (в том числе в качест- ве параметров функций NNAME и NEWTASK) и в качестве адресатов в опера- торе SEND. Если в качестве таковых параметров используется имя текущей единицы - задачи, то оно также должно быть описано как внешнее. Таким образом, передать сообщение процессу можно, идентифицируя его именем программной единицы-задачи, по которой он был образован (по имени класса), или по системному имени. Оператор TASK EXTERNAL должен быть размещен в программе-задаче до первого исполняемого оператора. - 7 - Имена (системные идентификаторы) процессов не имеют внешнего представления, они скрыты от пользователя, их можно присваивать пере- менным типа TASKID. Процесс может определить собственное имя, имя про- цесса,породившего его, и имя главного процесса программы с помощью стандартных функций MYTASKID, РАRENT и МАSTER. Определение имен про- цессов по номерам виртуальных процессоров приведено в п. 7. Созданные процессы загружаются и сразу начинают выполняться на процессорах,виртуальные (логические) номера которых заданы значениями параметра  1ia 0. Допускается использование одинаковых логических номеров для размещения процессов на одном виртуальном процессоре (для стати- ческой модели параллелизма это не так !). Конкретное отображение виртуальных номеров процессоров на процес- соры рабочей машины, способ загрузки процессов определяется реализаци- ей, например, конструкциями языка описания конфигурации (аналогично тому, как номера каналов ввода-вывода в стандартах Фортрана не закреп- лены, а определяются реализацией, в частности, языком управления зада- ниями). Процедура создания главного процесса программы и порядок его размещения на процессоре также определяется реализацией. При реализации статической модели параллелизма распределение про- цессов по процессорам производиться статически, на этапе подготовки задания. В этом случае, функции NEWTASK в программе отсутствуют и про- цессы запускаются при инициализации задачи. В статическом варианте имена процессов (системные идентификаторы) определяются с помощью функции GETTASKID, имеются еще ряд стандартных функций для работы в этом режиме (см. 7.). Примеры использования функций порождения процессов Операторы порождения будут иметь окружение программы-задачи С. TASK PROGRAM C TASK EXTERNAL A,B,READ,PRINT TASKID TI, TM(100),TM2(100,2) INTEGER K,KM(100),KM2(100,2) ............. END Инициализация процессов: 1 TI = NEWTASK(A,K) 2 TМ = NEWTASK(A,KМ) 3 TМ2 = NEWTASK(A,KМ2) - 8 - DO 4 I=1,100 4 TМ(I) = NEWTASK(A,KМ(I)) DO 5 I=1,100 TМ2(I,1) = NEWTASK(A,KМ2(I,1)) 5 TМ2(I,2) = NEWTASK(B,KМ2(I,2)) Операторы с метками 2 и 4 (3 и 5) производят одинаковые действия, но инициализация в форме 2 (3) предпочтительнее, так как эта запись позволяет производить инициализацию процессов параллельно. Отсутствие в Фортране 77 аппарата вырезок из массивов не позволяет иметь такую запись для алгоритмов: DO 6 I=1,99,2 TМ(I) = NEWTASK(A,KМ(I)) 6 TМ(I+1) = NEWTASK(В,KМ(I+1)) или TМ(1) = NEWTASK(READ,KМ(1)) TМ(100) = NEWTASK(PRINT,KМ(100)) DO 7 I=2,99 7 TМ(I) = NEWTASK(В,KМ(I)) В результате выполнения операторов: TI = NEWTASK(PRINT,1) 8 TI = NEWTASK(READ,2)) на виртуальном процессоре с номером 1 будет образован и запущен про- цесс PRINT, внутреннее имя которого потеряно и недоступно программе из-за выполнения оператора 8.Доступ к нему для передачи сообщений воз- можен только по программному имени, заказать от него прием сообщений невозможно. C процессом на втором процессоре возможен обмен сообщения- ми в обе стороны. В языке определена только одна синтаксическая конструкция исполь- зования функции NEWTASK - в операторе присваивания. Тем не менее вход- ные языки могут разрешать использование этой функции и в других кон- текстах, там, где употребляются переменные типа TASKID. Например, опе- ратор: SEND (NEWTASK(PRINT,MI)) RES породив процесс печати, передает ему данные через RES. - 9 - Виртуальные номера процессоров. Кодировка виртуальных номеров процессоров произвольная, также как задание номера меток программы. Эти номера могут быть переданы процес- су, который порождает другие, через каналы ввода, операторами передачи сообщений, а также сгенерированы программно. Одинаковые номера процессоров могут быть использованы для опти- мального распределения ресурсов путем выравнивания времени работы про- цессов. Определив время работы (число операций) самого время-емкого процесса, можно объединять на одном процессоре выполнение нескольких других процессов, если их суммарное время меньше.При этом можно уско- рить выполнение программы из-за упрощения коммуникаций между процесса- ми, выполняемых на одном процессоре. Виртуальные номера процессоров могут быть использованы для наст- ройки решающего поля. Параллельные алгоритмы, формулируемые в теорети- ческой постановке обычно как n-размерные, при программировании приво- дятся к параметрам реальной структуры решающего поля. Алгоритмы, реа- лизуемые как стандартные процедуры, также должны адаптироваться к структуре выделяемых ресурсов. Настройка структуры (под) программ под параметры вычислительной среды может управляться заданием номеров вир- туальных вычислителей. При запуске программы на конкретной вычислительной платформе воз- можно потребуется сопроводить программу спецификацией об используемых значениях номеров виртуальных процессоров и схемой их оптимальной дис- локации на вычислителях платформы, и об именах задач, связанных с эти- ми номерами для последующей загрузки соответствующих процессов. Конк- ретные реализации, оговаривая правила загрузки задач на процессоры, могут содержать средства задания порядка выполнения (приоритета) нес- кольких процессов на одном процессоре. Для статической модели параллелизма балансировка загрузки вычисли- тельной системы может производиться на уровне языка конфигурации, раз- мещением на одном физическом процессоре нескольких виртуальных. 3.2. Завершение программы и завершение процессов Выполнение программы на языке Fortran GNS завершается в следующих случаях: а) при завершении выполнения главного процесса (процеду- рой STOP или выходом через END главной программной единицы); б) при "авосте" в главном процессе; - 10 - в) при выполнении в каком-либо процессе программы стан- дартных процедур ABORT и FINISH. г) при выполнении в каком-либо процессе программы оператора FINISH. Из определения следует, что для завершения программы не требует- ся ожидания естественного (или авостного) завершения всех инициирован- ных процессов программы, в частности, завершения всех обменов сообще- ниями между ними и выборки поступивших сообщений из почтовых ящиков. Вопрос о буферах ввода-вывода при "авосте" в главном процессе решается соглашениями ОС. Выполнение одного процесса завершается в следующих слу- чаях: а) если выполняется одно из указанных выше условий, при- водящих к завершению всей программы; б) при выполнении оператора STOP в данном процессе; в) при выполнении оператора END в задаче, по которой об- разован процесс; RETURN,END в функциях и процедурах имеет традиционный смысл. г) в случае "авоста" в данном процессе. Таким образом любой процесс может завершить выполнение всей прог- раммы выполнением стандартных процедур ABORT, FINISH; завершение про- цесса другими способами не прекращает выполнение программы. В частнос- ти, при выполнении оператора END в задаче, процесс завершается, ссылка на него сохраняется. Проблема почтовых ящиков завершенных процессов решаются при реализации языка. При статической модели параллелизма работа программы завершается выполнением в одном из процессов ABORT или FINISH. В языке нет средств для определения статуса процесса, поэтому, проблемы использования процессора,освободившегося по завершению выпол- няемого на нем процесса, связаны с наличием динамической загрузки про- цессов и должны решаться программированием синхронизирующих механиз- мов. 3.3. Ввод-вывод Операторы ввода-вывода программы могут выполняться в каждом про- цессе. Предполагается наличие общей файловой системы. Если какой-либо процесс обращается к файлу, то оператор OPEN, открывающий этот файл, должен выполняться в этом же процессе. - 11 - 4. Передача сообщений Обмен информацией между процессами осуществляется с помощью пе- редачи сообщений. Для этого используются операторы: SEND  2  0  2- 0 послать сообщение и RECEIVE - принять сообщение. 4.1. Способы передачи сообщений Предусмотрено три способа передачи сообщений: синхронный, асинх- ронный и передача без ожидания. а.  _Синхронный способ При синхронном способе передачи сообщений посылающий и принимаю- щий процессы приостанавливают выполнение своих программ и переходят в состояние ожидания до тех пор, пока не выполнятся оба синхронных опе- ратора SEND и RECEIVE. Сообщения данного типа могут передаваться без использования буфе- ров почтовых ящиков, так как передача синхронного сообщения будет про- изводиться только при готовности абонентов к обмену и может происхо- дить непосредственно из памяти передающего процесса в память принимаю- щего процесса. Процесс может посылать синхронные сообщения как отдельному про- цессу, так и и группе процессов. В последнем случае процесс отправи- тель продолжит выполнение только после получения подтверждения о вы- полнении соответствующих операторов RECEIVE во всех процессах - полу- чателях. Получив сообщение, получатель группового синхронного сообще- ния может продолжить работу, не ожидая завершения всех остальных обме- нов по данному оператору SEND. Получатель синхронного сообщения может ждать его только от процесса, имя которого указано в параметре опера- тора RECEIVE, т.е нельзя заказать в одном операторе ожидание синхрон- ных сообщений от нескольких процессов. б.  _Асинхронный способ При асинхронном способе передачи сообщения посылающий процесс продолжает выполнение независимо от того, выполнил ли получающий про- цесс оператор RECEIVE или нет. Сразу же после выполнения оператора SEND процесс может изменить значения данных, перечисленных в списке передаваемых значений этого - 12 - оператора, однако абоненту передаются те значения, которые были на мо- мент выполнения оператора SEND. Выполнение асинхронного оператора RECEIVE и продолжение работы процесса - получателя производиться только после поступления сообще- ния. Если сообщение пришло к получателю до выполнения у него оператора RECEIVE, то сообщение помещается в почтовый ящик процесса без прерыва- ния его выполнения.Сообщения с одинаковым значением тега от одного и того же отправителя помещаются в почтовом ящике в том же порядке, как они посылались и в таком же порядке они будут выбраны операторами RE- CEIVE. Сообщения, передаваемые асинхронным способом, идентифицируются именами отправителя и тегами (положительными значениями целого типа). Имя отправителя можно опускать в процессе - получателе, т.е. можно за- казывать ожидание сообщений этого типа (с заданным тегом) от произ- вольного процесса. В этом случае отправителя можно идентифицировать при получения сообщения при помощи параметра SENDER в операторе RECEI- VE. Стандартные функции TESTMSG, TESTTAG, PROBE позволяют анализиро- вать наличие сообщений, значения тегов и имен отправителей асинхронных сообщений в почтовом ящике процесса и ,соответственно, управлять по- рядком выбора поступивших сообщений. Для организации селекции и установки режимов ожидания заданных асинхронных сообщений можно использовать также конструкции выбора (см. раздел 5.). в.  _Передача без ожидания При передаче сообщения способом "без ожидания" момент передачи сообщений (копирование данных для передачи в процессе отправителе и присваивание соответствующим переменным значений данных из принятого сообщения в процессе получателе) не определен в языке и зависит от системы интерпретации. При такой передаче работа обоих процессов (отп- равителя и получателя) продолжается после выполнения операторов этого вида, независимо от того, выполнилась ли фактически передача сообще- ния. Так как значения данных, указанных в списке переменных оператора SEND, могут быть изменены любым следующим оператором процесса, то пе- редаются такие значения, которые имеют эти переменные в момент факти- ческой передачи. Оператор приема сообщений данного типа формирует за- - 13 - явку на прием сообщения,а переменные, перечисленные в списке не изме- няются, если сообщение еще не поступило в почтовый ящик процесса на момент выполнения оператора. При поступлении сообщения, данные пересы- лаются из почтового ящика в память процесса (присваиваются соответс- твующим переменным) без прерывания его работы. В каждым операторе обмена этого типа один из его параметров - ло- гическая переменная FLAG служит для фиксации факта передачи сообщения. Значение этой логической переменной-флага связывается с фактом выпол- нения передачи данных, заданной оператором обмена для того процесса, в котором определена эта переменная. Система интерпретации присваивает флагу в процессе отправителе значение .TRUE. в момент снятия копии с данных отправителя для передачи, и флагу в процессе-получателе после присвоения этих значений переменным получателя. До выполнения операто- ра передачи / приема сообщения значение логической переменной - флага, связанной с этим оператором не определено. Определить факт передачи данных и приостановить выполнение процес- сов до выполнения фактической передачи сообщения этого типа (для отп- равителя - до снятия копии с передаваемых данных, для получателя - до поступления сообщения в почтовый ящик или записи переданных данных в поле задачи) можно при помощи стандартных процедур - MSGDONE, ALLDONE, TESTFLAG. Только установка значения флага в .TRUE. отправителю дает возмож- ность изменять переменные, перечисленные в операторе SEND, без риска изменить передаваемые данные, для получателя - начать использовать по- лученные данные.Использование этих логических переменных вне операто- ров передачи сообщений и перечисленных выше процедур не допускается. По аналогии с асинхронным протоколом допускается ожидание асинх- ронных сообщений от произвольного процесса (в операторах RECEIVE можно опускать имя отправителя). Замечание: Понятие "почтовый ящик процесса", используемое в данном описание языка, носит методический характер и служит моделью для пояснения се- мантических понятий аппарата передачи сообщений. Алгоритмы реализация этого аппарата зависят от особенностей вычислительной платформы и ее системного обеспечения. 4.2. Идентификация абонентов Идентификация абонентов при организации передачи сообщений может - 14 - производится по имени процесса (массиву имен) или идентификатору зада- чи, по описанию которой образован процесс. Есть способы безадресных (широковещательных) посылок сообщений - "всем", и приема от произволь- ного отправителя сообщений с заказанной "маркой" - тегом. Идентифика- ция абонентов может быть произведена: а) По имени процесса Основным способом идентификации абонентов при передаче сообщений является задание имени процесса (системного идентификатора) переменны- ми типа TASKID и стандартными функциями этого типа MYTASKID, РАRENT и МАSTER. Использование этих стандартных функций является единственным первоначальным способом сослаться из порождаемых процессов на имена порождающих процессов, так как начальный диалог между процессами воз- можен только на уровне порожденный-порождаемый. Путем обмена сообщени- ями можно организовать передачу имен процессов для организации произ- вольной абонентской сети. Переменные типа TASKID - параметры операторов передачи сообщений могут: - ссылаться на функционирующий процесс, - ссылаться на завершенный процесс, - иметь значение .NOTASKID., - быть не инициализированными. Реакция программы на три последних случая не оговаривается в языке и определяется реализацией. Одно из решений - игнорирование оператора обмена сообщениями с такими параметрами (кроме синхронных операторов, для которых такой случай следует считать "авостом" в программе). Про- цесс-отправитель имеет возможность организовать дублирование передава- емых сообщений для передачи их одновременно нескольким процессам-полу- чателем. Для этого допускается задание абонентов в параметрах операто- ра передачи сообщений в виде массива типа TASKID. Сообщение будет пе- редано при этом всем процессам, на которые есть ссылки через элементы массива. Данная массовая операция предпочтительнее передачи сообщений, организованной по-элементной циклической конструкцией. Цикл предписы- вает порядок перебора элементов массива - абонентов передачи, а для синхронного обмена и завершение очередной передачи до посылки следую- щего сообщения. Массовая операция обмена может проводиться параллельно и независимо для всех заказанных абонентов. Массовые операции ассимет- - 15 - ричны, нельзя заказать ожидание сообщения от нескольких процессов сра- зу. Теговая идентификация сообщений и конструкции выбора допускает не- которую вольность в указаниях об именах отправителей. б) По имени программной единицы-задачи Задание в операторе передачи сообщений в качестве адресата - полу- чателя имени программной единицы-задачи означает рассылку сообщений всем процессам, образованным по описанию указанной задачи на момент выполнения оператора. Случай, когда к этому моменту не было образовано ни одного процесса по указанному образцу, можно рассматривать по ана- логии с передачей сообщения процессу с "именем" - .NOTASKID. . Возмож- ность задать в качестве адресата имя главного процесса уточняется в описаниях входных версий языка. в) Безымянные абоненты Специальный идентификатор ALL в параметре адресата-получателя со- общения предписывает передать данное сообщение всем процессам програм- мы, инициализированным на данный момент. Передача сообщений двумя последними способами предполагает возмож- ность параллельной рассылки сообщений и исключение процесса, выполняю- щего оператор передачи сообщения, из списка абонентов - получателей. г) Помеченные сообщения При передаче сообщений асинхронным способом сообщения при отправ- лении помечаются целым числом - тегом. Эта разметка дает возможность абонентам идентифицировать сообщения от разных операторов передачи со- общений одного процесса. Получив сообщение с заданным тегом, процесс может узнать имя отправителя, через аппарат SENDERов. Это замечание верно и для передачи сообщений без ожидания. 4.3. Операторы передачи сообщений  _Операторы SEND и RECEIVE имеют вид:  Ш1.0 ┌────────────────────────────────┐ │ │ │ SEND ( 1sm 0 [ 1,ss 0]...) [ 1список 0] │ │ RECEIVE ( 1rm 0 [ 1,rs 0]...) [ 1список 0] │ │ │ └────────────────────────────────┘ - 16 -  Ш1.5 где  1sm  0или  1rm  0- спецификация сообщения - определяет адресата (процесс или процессы, которым посылается сообщение) или отправителя и способ синхрони- зации;  1список  0- список передаваемых данных имеет такой же вид, как списки в операторах ввода/вывода Фортрана 77, т.е. элементом списка может быть констан- та,имя переменной, переменная с индексом, имя массива или неявный цикл;  1ss 0 или  1rs 0 - дополнительная спецификация. Вид спецификации сообщения  1sm  0и  1rm  0зависит от способа синхрони- зации. а)  _Синхронный способ:  1sm  2есть 0 [TASKID =]  1адресат 0, где  1адресат 0  2есть  1adr 0  2или  0ALL, а  1adr -  0ссылка на функцию, имя переменной, элемента массива или имя массива типа TASKID или имя программной единицы-задачи. Если  1adr  0- имя программной единицы-задачи, то сообщение посылается всем процессам программы, образованным по образцу указанной программной единицы (исключая посылающую).процедуры. ALL - означает, что сообщение посылается всем процессам программы, образованным на момент выполнения опера- тора передачи сообщения,исключая процесс-отправитель.  1rm  2есть  0[TASKID =]  1t 0, где  1t  0- переменная или элемент масси- ва типа TASKID; параметр специфицирует процесс - отправитель. Когда  1adr 0 ( 1rm 0) - значение типа TASKID, оно должно ссылаться на незавершенный процесс. б)  _Асинхронный способ  1sm  0  2есть 0  2  0 [TAG=] 2  1ie 0, 1  0 [TASKID =] 2  1адресат  2или 0  1  0 TASKID 2  0= 2  1адресат 0, 1  0[TAG =]  1ie  1rm  0  2есть 0  2  0[TAG=]  1ie  0[,[TASKID =]  1t 0]  2или  0 TASKID 2  0= 2  1t 0, 1  0[TAG =]  1ie где  1адресат 0 и  1t 0 определяются как  1rm 0 для синхронного способа,  1ie  0- выражение целого типа, значение которого определяет тег сообщения. - 17 - в)  _Способ без ожидания  1sm  0  2есть  0[TASKID =]  1адресат 0, FLAG 2  0= 2  1l  1rm  0  2есть  0[TASKID =] 2  1adr 0, FLAG 2  0= 2  1l  2или  0  1  0[FLAG =] l где  1адресат 0 и  1adr 0 определяется как и для предыдущего способа;  1l 0 - имя логической переменной. Переменная  1l  0может использоваться также в стандартных процедурах MSGDONE( 1l 0) и TESTFLAG( 1l 0) (см. п.7.). В других си- туациях ее использование не допускается.  _ 0Дополнительная спецификация Дополнительная спецификация  1ss  0и  1rs  0, как видно из синтаксиса, яв- ляется необязательной.  1ss 0  2есть 0 ERR =  1l  2и 0 /  2или  0 SRSTAT =  1ios где  1l 0 - специфицирует метку, которой передается управление в случае ошибки при передаче сообщения;  1ios 0 - имя переменной или элемента массива целого типа; спе- цифицирует статус состояния (аналог спецификации IOSTAT 1  0 в операторах ввода/вывода) 1. В результате выполнения оператора, переменной  1ios  0присваивается значение O , если не было обнаружено ошибки, и положительное значение, если обнаружена ошибка. Классификация видов ошибок определяется реали- зацией языка. Если спецификация SRSTAT отсутствует, то значение стату- са состояния присваивается системной переменной. Если спецификация ERR отсутствует, то в случае ошибки, задача (и вся программа) завершается выполнением стандартной процедуры ABORT. В качестве дополнительной спецификации  1rs  0для оператора RECEIVE, помимо аналогичных спецификаций ERR и SRSTAT, можно также использовать необязательную спецификацию SENDER, т.е.  1rs  0  2есть 0  2  0ERR =  1l  2и 0 /  2или 0 SRSTAT =  1i  2и 0 /  2или  0 SENDER =  1t где  1t 0 - переменная типа TASKID. Cпецификацию SENDER полезно использовать, если отсутствует имя процесса-отправителя. Переменной  1t  0после выполнения оператора RECEIVE присваивается значение имени процесса-отправителя. - 18 - Замечание. 1.Способ передачи сообщения и число элементов в списках оператора SEND и соответствующего оператора RECEIVE должны совпадать; для каждо- го элемента - тип, а для массивов также размерность и конфигурация должны соответствовать друг другу. Конфигурация массива - это одномер- ный массив целого типа, размер которого равен размерности исходного массива, а элементы равны размерам соответствующих измерений. Несоответствие структуры данных при синхронной передаче считается ошибкой в обоих процессах , при других способах передачи - ошибкой в задаче-отправителе. 2. Если значение переменной адресата есть .NOTASKID. или ссылка на завершенный процесс, оператор обмена для этого процесса не выполня- ется, а спецификация SENDER получает значение .NOTASKID. . 3.Не считается ошибкой наличие в почтовом ящике невостребованных сообщений при завершении процесса. Использование операторов передачи сообщений Синхронный режим передачи сообщений По определению, синхронный режим передачи сообщений требует однов- ременного выполнения в процессах соответствующих операторов, что при расслогласовании работы процессов может быть источником "зависания" программы. Достоинством данного метода передачи сообщений является принципиальная возможность проводить обмен данными без использования системных буферов, что может ускорить время обмена. Операторы передачи сообщений с пустым списком данных могут ис- пользоваться для синхронизации вычислений программы. Для этого в процессе, управляющем синхронизацией, следует выпол- нить оператор: SEND(ALL), во всех процессах программы - RECEIVE (T1),где Т1 должен ссылаться на управляющую задачу. Управляющий про- цесс продолжиться только после выполнения во всех задачах оператора RECEIVE. Оператор SEND(А) требует синхронизации только от процессов, образованных по программе-задаче А, а SEND(ТМ) - от процессов, на ко- торые ссылаются элементы массива ТМ. Если процессам известно, что ран- деву будет требовать начальный процесс, то их синхронизирующий опера- тор может быть записан: RECEIVE (МАSТЕR()). Точная синтаксическая за- пись: Т1=МАSTER() RECEIVE (T1) - 19 - так как в параметрах операторов передачи сообщений не разрешается ис- пользования выражений. Реализации могут иметь расширенное толкование семантики, в частности, допускать использование функций типа TASKID в позициях переменных этого типа. Некоторые реализации могут запрещать в операторах приема сообщений неявные циклы, управляемые параметром, на- ходящимся в этом же списке ввода. Так, в Фортране МВК запрещены такие конструкции: RECEIVE (<..>) N, (KM(I),I=1,N) Асинхронный режим передачи сообщений Использование данного способа обмена сообщениями делает программу еще менее критичной к согласованию операторов обмена сообщениями, так как процесс-отправитель продолжает работу после передачи сообщения, не дожидаясь конца фактической передачи сообщения (и даже начала, так как система интерпретации "должна" сразу же, скопировав передаваемые дан- ные в буфер, "отпустить" процесс) . Получатель сообщений этого типа может выдавать директиву приема сообщения, только удостоверившись в наличии нужного сообщения в почтовом ящике процесса при помощи функ- ций: TESTMSG,TESTTAG,PROBE. Выполнение оператора RECEIVE без проверки наличия сообщения в почтовом ящике процесса, по аналогии с синхронным способом обмена, приводит к задержки выполнения процесса до приема со- общения с заказанным тегом и ,возможно, с заданным именем отправителя. Но в отличие от синхронного способа, асинхронный способ позволяют про- водить селекцию поступающих сообщений при помощи конструкций выбора. Пусть процесс может получать сообщения с тегом 1, но от процесса TI - скаляр целого типа, а от процесса TM(1) - массив из 100 целых чисел. Тогда,прием таких сообщений может быть запрограммированно так: IF (TESTTAG(1)) THEN SELECT MESSAGE CASE(1,TI) RECEIVE (1) K CASE(1,TM(1)) RECEIVE (1) KM END SELECT END IF или: - 20 - SELECT MESSAGE CASE(1,TI) RECEIVE (1) K CASE(1,TM(1)) RECEIVE (1) KM CASE DEFAULT GO TO 2 END SELECT 2 CONTINUE Ожидание этих сообщений, то есть, по аналогии с синхронной переда- чей сообщений, прерывание работы процесса до получения сообщения (в данном случае любого из ожидаемого) записывается так: SELECT MESSAGE CASE(1,TI) RECEIVE (1) K CASE(1,TM(1)) RECEIVE (1) KM END SELECT Если сообщения различаются тегами, то конструкция их ожидания мо- жет иметь вид: SELECT MESSAGE CASE(1) RECEIVE (1) K CASE(2,TM(1)) RECEIVE (2) KM END SELECT Режим передачи сообщений без ожидания Передачи сообщений этого типа рекомендуется использовать для пере- дачи данных "впрок", заблаговременно. Если после операторов SEND / RE- CEIVE без ожидания, поместить операторы: CALL MSDONE(L), семантика операторов будет совпадать с семантикой асинхронных операто- ров. Следует иметь ввиду, что при использовании операторов данного ви- да в цикле без использования процедур ожидания фактической передачи сообщений возможно искажение передаваемых данных; семантика функции TESTFLAG при этом будет двусмысленной. - 21 - Структура элементов списка передаваемых сообщений Структура элементов списка передаваемых (принимаемых) сообщений, как объявлено, совпадает с списком ввода вывода операторов обмена Фортрана. Широкие возможности предоставляет аппарат неявных циклов. Пусть имеются описания: REAL A(10),B(5,5). Тогда оператор: SEND(ALL)A,(B(I),I=1,5),(B(I,1),I=1,5),(B(I,I),I=1,5) перешлет всем процессам программы следующие объекты: - массив А целиком, - первый столбец массива В, - диагональные элементы массива В Этим способом можно организовать не только передачу (прием) любых вырезок их массивов, но и множества одинаковых данных, например, пе- реслать пять копий массива В: SEND(ALL)(B,I=1,5) 5. Конструкция выбора Конструкции выбора служат для анализа сообщений, переданных в почтовый ящик процесса асинхронным способом.Конструкция выбора позво- ляет, в зависимости от того, какие сообщения, передаваемые асинхронным способом, уже поступили (и, возможно, с учетом дополнительных усло- вий), выполнить ту или иную последовательность операторов (например, содержащую оператор приема поступившего сообщения) или приостановить выполнение до поступления сообщения и затем выполнить соответствующую последовательность операторов. Конструкция выбора имеет вид: SELECT MESSAGE [CASE( 1селектор 0)  1блок 0]... [CASE DEFAULT  1блок 0] END SELECT где  1селектор  0  2есть  0  2  0[TAG=]  1ie  2и 0 /  2или 0  2  0[TASKID=]  1t  2и 0 /  2или 0 COND=  1le где  1ie 0 - выражение целого типа (тег);  1t 0 - переменная или элемент массива типа TASKID;  1le 0 - логическое выражение; - 22 -  1блок  0- это последовательность выполняемых операторов, которая должна удовлетворять тем же требованиям, что и блоки конструкции IF-ENDIF в Фортране 77, а именно: передача управления внутрь блока извне запрещена, однако внутри блока переходы допускаются; разрешается выход из конструкции, допускаются операторы CALL и обращения к функци- ям 1;  0если блок содержит управляющую конструкцию IF-ENDIF или SELECT MESSAGE - END SELECT , то эта конструкция должна целиком принадлежать блоку. На оператор CASE нельзя передавать управление. Переход на опе- ратор END SELECT разрешен только внутри конструкции. Если значение логического выражения хотя бы в одной COND-специфи- кации - .TRUE. и сообщение, специфицированное в том же операторе CASE, поступило, то выполняется соответствующий блок (если таких операторов CASE несколько, то выполняется один из блоков по усмотрению системы интерпретации, для которых выполняются эти условия). Если же нет опе- ратора CASE, удовлетворяющего таким условиям, то выполняется блок, следующий после CASE DEFAULT. Если в операторе CASE отсутствует COND-спецификация, полагается что COND=.TRUE. Если оператор CASE DEFAULT отсутствует и значения всех логических выражений - .FALSE., то это ошибка периода выполнения. Если (при от- сутствии блока CASE DEFAULT) для всех тех логических выражений, значе- ние которых - .TRUE., соответствующее сообщение еще не поступило, то процесс переходит в состояние ожидания. 6. Стандартные процедуры Список стандартных процедур, которые введены в язык для реализа- ции механизма управления работой процессов, приведен в таблице . В ди- намической модели параллелизма процедура NEWTASK порождает вычисли- тельный процесс и вырабатывает его имя. С помощью стандартных функций MYTASKID(), MASTER(), РАRENT() можно получить имя процесса, вызвавшего функцию (имя текущего процесса), имя начального процесса или имя про- цесса, породившего текущий, соответственно. В статическом режиме, т.е. при отсутствии вызова функции NEWTASK, результат выполнения функций PARENT() и MASTER() - константа .NOTAS- KID. Функция GETTASKID ( 1proc 0) возвращает имя процесса , расположенного на виртуальном процессоре с номером  1proc 0. Тип результата функции - TASKID. - 23 - Целая функция NNAME ( 1name 0) возвращает количество процессов, соз- данных из программной единицы-подзадачи с именем  1name 0. Аргумент функ- ции должен быть указан в операторе TASK EXTERNAL. Если он равен '*' , то возвращается число всех виртуальных процессоров программы. Целая функция NVIRPR ( 1name 0,array,array_lengr) возвращает коли- чество процессов, созданных из программной единицы-подзадачи с именем  1name 0. Этот аргумент функции должен быть указан в операторе TASK EXTER- NAL. Если он равен '*' , то возвращается число всех виртуальных про- цессоров программы. Функция также заносит в массив array (идентифика- тор массива или переменная с индексом) номера виртуальных процессоров, на которых образованы процессы с именем name или всех процессоров программы (для name = '*'). Значение параметра array_lengr задает це- лое число элементов массива array, куда следует записать номера про- цессоров. Если параметр больше, чем число записываемых процессоров, то значение функции - фактическое число процессоров, а в массив заносятся только эти номера. Если параметр array_lengr меньше, чем число записы- ваемых процессоров, то значение функции - фактическое число процессо- ров, умноженное на -1, а в массив заносятся только заданное число про- цессоров. Данная функция отличается от функции NNAME наличием бокового эффекта. Целая функция NTASKS () возвращает количество всех процессов (чис- ло виртуальных процессоров) в выполняемой программе. Целая функция MYVP () возвращает номер виртуального процессора для процесса, вызвавшего эту функцию. Результат функции TESTMSG( 1i 0, 1t 0) - .TRUE. или .FALSE. в зависимос- ти от того, находится ли в почтовом ящике задачи, вызвавшей функцию, сообщение от задачи с именем  1t  0с тегом, равным  1i 0. Результат функции TESTTAG( 1i 0)  1-  0.TRUE. или .FALSE. в зависимости от того, находится ли в почтовом ящике задачи сообщение с тегом, рав- ным  1i 0. Функция PROBE() последовательно выдает значение тега тех сообще- ний, которые уже содержатся в почтовом ящике. Если функция вызывается несколько раз, сканируется почтовый ящик; когда почтовый ящик пуст (или перебрано все содержимое ящика) - выдается признак -1. (Из этого следует рекомендация не использовать эту константу в качестве тега.) При реализации возможно уточнение семантики функции, например, опреде- ления правила начальной установки указателя функции, порядка перебора содержимого ящика. - 24 - Реализация данной функции в языке Фортран МВК. Функция PROBE работает с очередью асинхронных сообщений, посту- пивших в почтовый ящик процесса. Каждый элемент очереди идентифициро- ван тегом сообщения и TASKID-ом процесса-отправителя. Функция исполь- зует внутренний, недоступный пользователю, указатель на текущий эле- мент очереди. Функция PROBE возвращает тег текущего элемента очереди и сдвигает указатель на следующий элемент очереди. Если очередь исчерпа- на (или была пуста), то функция возвращает значение -1. Указатель ус- танавливается на начало очереди в следующих случаях: - первоначально, при инициализации процесса; - при выполнении асинхронного оператора RECEIVE; - при обращении к любой функции редукции. Эти функции можно использовать для анализа почтового ящика при асинхронном способе передачи сообщения без использования конструкций выбора. Cледующие три процедуры предназначены для режима без ожидания. Процедура MSGDONE( 1l 0) организует режим ожидания (прерывание выпол- нения процесса) до тех пор, пока передача сообщения с FLAG =  1l  0не бу- дет фактически выполнена. Процедура ALLDONE() организует ожидание фактического выполнения передачи всех сообщений, которые передаются способом без ожидания. Функция TESTFLAG( 1l 0) выдает значение .TRUE. или .FALSE. в зависи- мости от того, выполнена ли фактически передача сообщения с FLAG =  1l. Использование функций с параметром FLAG =  1l  0корректно только пос- ле выполнения операторов SEND / RECEIVE с этим флагом. Процедура SETNAME( 1c 0) присваивает имя (строку символов - с) теку- щему процессу, а функция MYNAME() выдает это имя или символ ", если имя не присваивалось. Эти две функции предназначаются для отладки. Процедура ABORT( ) - вызывает завершение всей программы. Процедура FINISH( ) - вызывает завершение всей программы. ┌───────────┬────────────┬───────────────────┬────────────┐ │ Имя │ Число │ Тип или класс │ Тип │ │ процедуры │ аргументов │ аргументов │ результата │ │ │ ├─────────┬─────────┤ │ │ │ │ 1 │ 2 │ │ ├───────────┼────────────┼─────────┼─────────┼────────────┤ │ │ │ │ │ │ │ NEWTASK │ 2 │ n │ i │ t │ - 25 - │ MYTASKID │ 0 │ - │ - │ t │ │ MASTER │ 0 │ - │ - │ t │ │ PARENT │ 0 │ - │ - │ t │ │ GETTASKID │ 1 │ i │ - │ t │ │ NNAME │ 1 │ n │ - │ i │ │ NTASKS │ 0 │ - │ - │ i │ │ MYVP │ 0 │ - │ - │ i │ │ TESTTAG │ 1 │ i │ - │ l │ │ TESTMSG │ 2 │ i │ t │ l │ │ TESTFLAG │ 1 │ l │ - │ l │ │ PROBE │ 0 │ - │ - │ i │ │ MSGDONE │ 1 │ l │ - │ - │ │ ALLDONE │ 0 │ - │ - │ - │ │ ABORT │ 0 │ - │ - │ - │ │ FINISH │ 0 │ - │ - │ - │ │ SETNAME │ 1 │ c │ - │ - │ │ MYNAME │ 0 │ - │ - │ c │ └───────────┴────────────┴─────────┴─────────┴────────────┘  _Примечание В таблице используются следующие обозначения: t - TASKID l - LOGICAL n - имя программной единицы i - INTEGER c - CHARACTER  _Процедура выдачи реального времени SYSTEM_CLOCK (COUNT, COUNT_RATE, COUNT_MAX) Для выдачи информации из часов реального времени имеется подпрограмма SYSTEM_CLOCK. Процедура имеет три аргумента, все три аргумента - выходные и они целого типа. Первому аргументу (COUNT) присваивается текущее значе- ние процессорных часов. Значение процессорных часов увеличи- вается на единицу для каждого такта часов, пока не достигнет максимального значения (COUNT_MAX) и устанавливается в нуль для следующего такта (т.е. значение находится в интервале от 0 до COUNT_MAX). Второму аргументу (COUNT_RATE) присваивается значение равное количеству тактов процессорного времени в секунду, третьему (COUNT_MAX) - максимальное значение, которого может достигнуть COUNT. - 26 - 7. Функции редукции В язык введены функции редукции с двумя параметрами, реа- лизующие массовые поэлементные операции. Операция редукции вы- полняются в среде процессов, на которые есть ссылки из одного из параметров функции данного типа - массива типа TASKID. Все эти процессы должен вызывать одинаковую функцию (и в которых указана одинаковая общая среда выполнения), которые выполняет- ся синхронно, и результаты возвращаются каждому процессу, со- держащему обращение. Редукция применяется для всех переменных, заданных другим параметром - аргументом операции (для каждого элемента массива отдельно, если параметр - массив) по всем процессам, указанным в обращении. При этом, типы,размерность и конфигурация параметров-массивов (аргументов операции) во всех процессах должны совпадать. Результат выполнения функции, рас- сылаемый всем процессам среды, имеет тип, размерность и конфи- гурацию аргумента. Процедура TSORT( 1t 0), входящая в состав функции редукции, где  1t  0- массив типа TASKID, служит для указания (не обязатель- ного) о предстоящих выполнениях функций редукции в среде про- цессов, на которые ссылаются элементы массива t. Используется для оптимизации межпроцессорных обменов при выполнении опера- ций редукции. Перечень функций редукции ┌──────────┬───────────┬────────────┬──────────────────┐ │ Имя │ Тип │ Тип │ Назначение │ │ процедуры│аргументов │ результата │ │ │ ├─────┬─────┤ │ │ │ │ 1 │ 2 │ │ │ ├──────────┼─────┼─────┼────────────┼──────────────────┤ │ │ │ │ │ │ │ PMAXVAL │r/d/i│ t │ r/d/i │ Максимальное │ │ │ │ │ │ значение │ │ PMINVAL │r/d/i│ t │ r/d/i │ Минимальное │ │ │ │ │ │ значение │ │ PALL │ l │ t │ l │ Конъюнкция эле- │ │ │ │ │ │ ментов массива │ - 27 - │ PANY │ l │ t │ l │ Дизъюнкция эле- │ │ │ │ │ │ ментов массива │ │ PCOUNT │ l │ t │ i │ Число элементов │ │ │ │ │ │ .TRUE. │ │ PPRODUCT │r/d/i│ t │ r/d/i │ Произведение эле-│ │ │ │ │ │ │ │ ментов массива │ │ PSUM │r/d/i│ t │ r/d/i │ Сумма элементов │ │ │ │ │ │ массива │ │ TSORT │ t │ - │ - │ Упорядочение │ │ │ │ │ │ массивов среды │ └──────────┴─────┴─────┴────────────┴──────────────────┘  _Примечание В таблице используются те же обозначения, что и в преды- дущей таблице. Символ "/" означает "или".  Ш1.5  _Примечание В таблице используются те же обозначения, что и в таблице 1., а r обозначает REAL. 7.1. Использование функций редукции Если из порожденных оператором: TI = NEWTASK(G,MI) про- цессов задачи G один из них, с наименьшим значением S, на не- котором этапе работы должен исключатся из дальнейшей работы - завершаться авостом (изменять алгоритм счета, передавать свои результаты на печать и т.д.), то если: - в задаче G описать TASKID LTI(<длина, равная длине TI>), - в процессе, порождаемом процессы класса G, выполнить после их порождения: SEND(TI)TI, а в процессах класса G перед началом работы: RECEIVE (PARENT) LTI , то с помощью функций редукции можно скорректировать работу процессов оператором: IF(S .EQ. PMINVAL (S,LTI)) ABORT() . Из определения функций редукции не следует требование вы- полнение редукции для процессов одного класса (образованных по одному описанию задачи). Так, функции суммирования, одновременно выполненные в разных процессах в среде из двух процессов: 1 A = PSUM(B,T) 2 A1 = PSUM(B1,T1) поэлементно просуммируют массивы В,В1 и результаты занесут в - 28 - массивы А.А1, т.е. А(i) = A1(i) = B(i)+B1(i) , если: - массивы А,А1,В,В1 имеют одинаковый тип, размер и конфи- гурацию, - обе задачи, по которым были образованы процессы, выпол- няющие операторы 1 и 2, содержат описание массивов:TASKID T(2) ,TASKID T12) элементам которых присвоены значения - имена про- цессов среды. 7.2. Использование статической модели параллелизма Пусть, необходимо написать параллельную программу суммирования элементов массива, которая сама настраивалась на число процессоров, выделяемых ей для работы. Программа суммирования может быть записана так: TASK PROGRAM SUM C Параметризация максимальной длины суммируемого массива и тега PARAMETR (NA=100000,NT=13) REAL A(NA) TASKID T C Ожидание вызова, N - длина массива, подлежащая суммированию C Фиксация в T имени вызывающего процесса, асинхронно 1 RECEIVE (TAG=NT,SENDER=T) N C Прием суммируемого массива по синхронному протоколу RECEIVE (TASKID=T) (NA(I),I=1,N) S = 0.0 DO I = 1,N S = S + NA(I) ENDDO C Отсылка результата в вызывающий процесс, асинхронно SEND (TAG=NT+1,TASKID=T) S C Переход в начало для многократного суммирования GO TO 1 END Обращение к процессу суммирования может многократно производится по имени процесса SUM из любого процесса программы последовательностью операторов: SEND (SUM,TAG=NT) N SEND (SUM) (A(I),I=1,N) RECEIVE (TAG=NT+1) S - 29 - Естественно, значение NT должны быть согласовано с значением тега в программе SUM. В вызывающем процессе должны находиться описания A и SUM ( TASK EXTERNAL SUM), определено значение N. Модификация программы для параллельного суммирования с коэффициен- том распараллеливания, равным числу инициализированных при задании конфигурации процессов класса SUM, может быть проведена так: В вызывающем процессе описывается массив MCPU целого типа с длиной, равной максимальному числу виртуальных процессоров, на которых возмож- на инициализация процессов класса SUM. Перед обращением определяется число процессов SUM и квота элемен- тов массива суммирования для каждого процесса SUM (общая его длина принимается за N). NSUM = NVIRPR(SUM,MCPU,NNAME(SUM)) C Вычисление квоты для суммируемых сегментов массива N1 = N/NSUM N2 = N1 SSUM = 0.0 DO J=1,NSUM C Последняя длина может быть длиннее N1, если N не кратно NSUM IF (J.EQ.NSUM) N2 = N-(J-1)*N1 SEND (TASKID=GETTASKID(MCPU(J)),TAG=NT) N2 SEND (TASKID=GETTASKID(MCPU(J)))(A(I),I=1+J*N1-N1,1+J*N1-N1+N2) SELECT MASSAGE CASE (TAG=NT+1) RECEIVE (TAG=NT+1) S SSUM = SSUM+S END SELECT ENDDO Манипулируя только числом порожденных процессов SUM при задании конфигурации можно, не изменяя программы, при ее исполнении менять степень распараллеливания суммирования. В данном примере функции расп- ределения работ были отданы вызывающей программе. Для управления параллельными работами в самой процедуре суммиро- вания (или иной распараллеливаемой процедуре) можно использовать другие приемы программирования. Пусть, вызывающая программа отдает массив(ы) для обработки одной процедуре (процессу), которая сама будет распараллеливать процесс вы- числений по своему алгоритму, с учетом наличия в вычислительной среде - 30 - однородных процессов. Следующий оператор и его окружение в вызывающей программе очевиден. NSUM = NVIRPR(SUM,MCPU,NNAME(SUM)) Далее, процесс отправляет первому (возможно единственному) массив для обработки и принимает результаты. SEND (TASKID=GETTASKID(MCPU(1)),TAG=NT) N SEND (TASKID=GETTASKID(MCPU(1)))(A(I),I=1,N) RECEIVE (TAG=NT+1) S Теперь необходима модификация описания процедуры SUM. TASK PROGRAM SUM PARAMETR (NA=100000,NT=13,MAXCPU(100)) REAL A(NA) TASKID T INTEGER MCPU(MAXCPU) NSUM = NVIRPR(SUM,MCPU,NNAME(SUM)) 1 IF (MCPU(1).NQ.MYVR()) GO TO 2 RECEIVE (TAG=NT,SENDER=T) N RECEIVE (TASKID=T) (NA(I),I=1,N) N1 = N/NSUM N2 = N1 SSUM = 0.0 DO J=2,NSUM IF (J.EQ.NSUM) N2 = N-(J-1)*N1 SEND (TASKID=GETTASKID(MCPU(J)),TAG=NT) N2 SEND (TASKID=GETTASKID(MCPU(J)))(A(I),I=1+J*N1-N1,1+J*N1-N1+N2) SELECT MASSAGE CASE (TAG=NT+1) RECEIVE (TAG=NT+1) S SSUM = SSUM+S END SELECT ENDDO DO I = 1,N1 SSUM = SSUM + NA(I) ENDDO SEND (TAG=NT+1,TASKID=T) SSUM GO TO 1 2 RECEIVE (TAG=NT,SENDER=T) N RECEIVE (TASKID=T) (NA(I),I=1,N) - 31 - S = 0.0 DO I = 1,N S = S + NA(I) ENDDO SEND (TAG=NT+1,TASKID=T) S GO TO 1 END 8. _Литература 1. Система программирования Фортран GNS. Описание языка. Отчет Инс- титута прикладной математики им. М.В.Келдыша РАН. Москва, 1995, 20 с. 2. Thole C.-A. Proposal for a Fortran Syntax Specification for distributed memory architectures. Version 1.0, April 30, 1990 3. Фортран-МВК, Отчет ИПМ N ______ , 1995 г.