- •Курский государственный технический университет
- •Предисловие
- •Введение
- •3.1.3.4 Конвейер команд в устройстве управления процессором
- •4 Теоретические основы функциональной организации многопроцессорных вс
- •4.1 Параллелизм на уровне системного программного обеспечения
- •4.1.1 Особенности мультисистемных операционных систем (мос) параллельных вс.
- •Алгоритм построения новой матрицы смежности Cp.
4 Теоретические основы функциональной организации многопроцессорных вс
4.1 Параллелизм на уровне системного программного обеспечения
4.1.1 Особенности мультисистемных операционных систем (мос) параллельных вс.
Реализация потенциальных возможностей повышения производительности, заложенных структурной организацией параллельных ВС, невозможна без развития операционных систем и создания их нового класса: мультисистемных операционных систем (МОС). В них по сравнению с одно процессорной ОС появляется ряд дополнительных задач управления для автоматизации исполнения асинхронных параллельных вычислительных процессов. Вспомним определение процесса.
Процесс – это совокупность работающей программы, данных и всей информации о ее состоянии и используемых ею ресурсах ВС. Процесс формируется на основании системного вызова, по которому выполняется полная начальная инициализация процесса, а именно вызов программы, определение мест хранения данных, назначения начальных адресов и смещений в памяти т.д.
С целью уменьшения затрат времени на начальную инициализацию во многих случаях процесс можно создать путем копирования любого старого процесса. Каждый процесс, в том числе и скопированный со старого, функционирует в независимом виртуальном адресном пространстве.
Дополнительные функции МОС:
Организация параллельного исполнения программ или параллельных ветвей одной сложной программы одновременно на нескольких процессора, обеспечивая высокую и равномерную их загрузку при переменном их числе с учетом выбывания при отказах и пополнения после их восстановления. Основные принципы такой организации – асинхронность запуска программ на разных процессорах, независимость между программами и процессорами с возможностью рестарта программы, прерванной в отказавшем процессоре, на любом исправном процессоре. Основные пути решения – применение программ планировщиков и диспетчеров, составляющих и реализующих оптимальное расписание запуска параллельных программ, или потоковая организация их запуска по мере готовности операндов.
Управление основной памятью ВС, в том числе общей памятью в мультипроцессорах, обеспечивая возможность обращения в любой ее модуль как любого обрабатывающего процессора, так и любого процессора ввода – вывода; оптимизацию управления очередями обращений в модули памяти нескольких процессоров с минимизацией времени их ожидания доступа в память; создание «почтовых ящиков» (буферов обмена) для обмена информацией между процессорами через память и т.п. Обеспечение когерентности строк кэш- памятей процессоров и страниц виртуальной памяти с помощью ведения централизованных справочников их состояний. Организация виртуальной совместно используемой распределенной памяти (DSM).
Повышение надежности и коэффициента готовности ВС, используя избыточность однотипных устройств системы. Обнаружение и исправление ошибок, вызванных сбоями и отказами устройств, без остановки системы. Обеспечение высокой достоверности контроля, например путем регулярной передачи соседним процессорным блокам трех видов осведомительных сигналов: «сердцебиение» по каждому конвейерному такту, «пока жив» и « подвеска процесса (или процессора)» с контролем по истечению допустимых тайм-аутов. Учет результатов прохождения контрольных точек в программах: успешно, с устранением последствий сбоя путем многократного повторения участков между двумя контрольными точками, с невозможностью такой коррекции ошибок.
Ведение журнала учета степени надежности устройств ВС и их старения по возрастанию интенсивности сбоев и классификации состояния устройства: устранимый сбой или отказ. Управление реконфигурацией структуры системы с отключением от интерфейсов отказавших устройств и рестартов на других устройствах прерванных в них программ.
4. Разрешение конфликтов между параллельными вычислительными процессами при требовании ими общих ресурсов: процессоров, памяти, устройств ввода- вывода, массивов данных, почтовых ящиков, программных модулей МОС, обслуживающих их прерывания и системные вызовы.
Основной механизм разрешения конфликтов – создание и постоянное ведение множества очередей к разным ресурсам с учетом приоритетов процессов, а также динамическое изменение уровней приоритетов процессов. Последнее используется для
- оптимизации обслуживания пользователей с учетом разной сложности их задач;
- привилегированной обработки программ системного ПО, в том числе организации их параллельной обработки, вытесняя из процессоров прикладные программы;
- предотвращение тупиковых ситуаций в совокупности параллельных процессов.
5. Синхронизация асинхронных параллельных процессов в дополнение к механизму приоритетных очередей для
-поддержания требуемого отношения предшествования в системе процессоров (допустимой очередности захвата общего ресурса, например общей области постепенно модифицированных данных);
-взаимного исключения, например при работе с почтовым ящиком;
-учета возможности выполнения взаимодействия между процессами, например при передаче сообщений в мультикомпьютерах.
Например, несмотря на то, что какой- то приостановленный или прерванный процесс окажется первым в очереди, его необходимо удержать в нерабочем состояние и уступить очередь другому процессу из-за нарушения первым очередности предшествования или неготовности части его входных операндов, еще не вычисленных другими параллельными процессом.
6. Предотвращение тупиков (клинчей, дедлоков, «мертвых объятий») в системе синхронизованных асинхронных параллельных процессов. Их возникновение обусловлено необходимостью названной выше синхронизации с приостановкой (блокировкой) нескольких процессов.
В этом случае возможно образование замкнутых цепей их взаимного ожидания разблокирования, когда они не освобождают часть захваченных ими ресурсов, требуемых для продолжения других процессов, а последние в свою очередь не освобождают другие ресурсы, требуемые для продолжения первым. Система останавливается как при отказе, но при полностью исправных устройствах. Известны системные программные средства для предотвращения, недопущения и обнаружения тупиков, которые мы рассмотрим ниже.
Функции управления параллельными процессами уже реализованы в последних версиях операционных систем UNIX(POSIX,SOLARIS,LINUX),Windows(NTи выше). Все названные выше задачи МОС решаются операционными системами мультикомпьютеровCrayT3Eи кластерных ВС. Причем в наиболее мощных кластерах, например в отечественной системе МВС-1000М, уже применяются двухуровневые распределенные МОС и файловые системы.
4.1.2 Фундаментальные вопросы организации системного ПО параллельных ВС
Общие принципы организации системного ПО многопроцессорных ВС можно обобщить в пяти фундаментальных вопросах:
-модели управления;
- степень распараллеливания процессов;
- вычислительные парадигмы;
-методы коммуникации;
- базистые элементы синхронизации.
Модель управленияопределяется тем, сколько в ней потоков управляющих команд: один или несколько. Современные МОС поддерживают две модели управленияSIMD(OKMD) иMIMD(MKMD). В первой модели имеется одна программа и один счетчик команд в ведущей ЭВМ, но несколько наборов данных, обрабатываемых в ведомой параллельной ВС по одной и той же команде в каждом командном цикле. Каждый процессор ведомой системы упрощен, содержит только АЛУ и память, но схема декодирования команд отсутствует. Только ведущая ЭВМ вызывает команды и указывает всем АЛУ ведомой системы, какую одинаковую операцию они должны выполнить в данном командном цикле системы.
Вторая модель предполагает наличие нескольких потоков управления, каждый из которых содержит собственный счетчик команд, память и локальные переменные. Каждый поток управления выполняет свою собственную программу над своими данными и время от времени может взаимодействовать с другими параллельными потоками управления.
Распараллеливание процессов и соответственно параллелизм управления ими можно вводить на разных уровнях, либо только на одном из них, либо на нескольких. Самый низкий уровень – это параллелизм команд, использованный в суперскалярных и VLIW- процессорах. Следующий уровень- параллелизм на уровне блоков команд программы (тредов), разновидностью которого является параллелизм вызывающей и вызываемой процедур, если первой не требуется ждать завершения последней или если организована ее агрессивная обработка на неуточненных спекулятивных результатах последней. Для каждого процесса в современных МОС могут порождаться несколько потоков управления, работающих параллельно в пределах адресного пространства основного процесса.
Потоки - это подпроцессы, разделяющие адресное пространство и глобальные переменные основного процесса, полагая, что разные процессы обычно не разделяют общего адресного пространства.
Высший уровень в современных МОС- это параллелизм нескольких разных процессов, которые могут работать над решением одной крупной задачи, но каждый в своем отдельном адресном пространстве.
Вычислительная парадигма – это метод структурирования способа организации параллельно- последовательного выполнения множества потоков или процессов. Основные парадигмы, встречающиеся в параллельных ВС.
Одна программа – несколько потоков данных(SIMD-архитектуры).
Конвейер-это конвейерная организация исполнения процессов, так называемый программный конвейер.
Фазированное вычисление с барьерной синхронизацией. Фаза – это часть работы, выполняемая параллельными процессами одного итого же яруса. Фаза завершается только после окончания этой части работы всеми параллельными процессами яруса. Только после этого все процессы синхронно начинают выполнение следующей части работы в следующей фазе. Такая синхронизация, требующая ожидания завершения самого позднего процесса и синхронного запуска последующих процессов, называется барьерной. Распределение частей работы параллельных процессов яруса по фазам выполняется программистом.

Pi1- первая часть работыi-го процесса;
Pi2- вторая последовательно исполняемая часть работы того же самогоi-го процесса.
Метод « разделяй и властвуй «, когда один сложный процесс вначале запускается, а затем иерархически по дереву или « гамаку» запускает параллельную и последовательную обработку нескольких процессов, которые аналогично запускают (или порождают) своих последователей (приемников).

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

Работающий процесс получает из очереди следующую задачу после завершения предыдущей, или прерывания.
Именно эта парадигма удачно подошла при создании архитектуры мультискалярного микропроцессора типа ММММ. ( Мультитредовой мультискалярной микросистемы).
Методы коммуникации. Взаимодействие параллельных процессов друг с другом организуется двумя основными способами: 1) на основе использования общих переменных; 2) путем передачи сообщений. Первый применяется в системах с общей памятью. Все процессы имеют доступ к общей памяти и взаимодействуют, записывая и считывая информацию в общей области памяти: логическом регистре, странице, почтовом ящике.
Например, одна и та же страница может быть отображена в адресные пространства двух или нескольких процессов, а затем общие переменные можно записывать и считывать в ней обычными машинными командами LOADиSTORE.
Второй подход- взаимодействие путем передачи сообщений применяется в мульти- компьютерах. Для этого в системах их параллельного программирования применяются коммуникационные примитивы send,receive, которые обычно реализуются как системные вызовы услуг МОС. Вsendуказывается адрес процесса – получателя, который поreceiveкопирует полученное сообщение в свое адресное пространство.
В мультикомпьютерах с целью упрощения прикладного параллельного программирования часто сочетают оба способа коммуникации: на нижнем процессорном уровне - передача сообщений, а на высшем прикладном пользовательском уровне – обмен через общие переменные в виртуальной общей памяти, организуемой МОС.
Количество получателей и отправителей сообщений в общем случае не равно единице. Если имеются один отправитель и один получатель, то такое взаимодействие называют индивидуальным (двухточечным). Если сообщение отправляется группе или всем процессам, то такое взаимодействие называется групповым (широковещательным, мультивещанием).
Базисные элементы синхронизациинеобходимо вводить в параллельное ПО по целому ряду причин, названных ранее в п 4.1.1. Наиболее важная из них - необходимость взаимного исключения процессов при использовании общих переменных для коммуникации. Нужно обеспечивать, чтобы во время записи одним процессом чего- либо в общую структуру данных никакой другой процесс не смог считывать эту же пока недостоверную структуру. Требуется выдерживать отношения предшествования между процессами при работе с общей структурой данных, а также блокировать процессы инициаторы, если инициируемые процессы не готовы к взаимодействию. Все эти проблемы синхронизации решаются путем введения в параллельные программы базисных элементов: семафоров, мьютексов и критических секций (интервалов).
При групповом взаимодействии, в парадигмах фазированных вычислений и «разделяй и властвуй» необходимо блокировать группу процессов, пока заданная фаза работы не завершается, или в более простом варианте, пока все параллельные процессы яруса не завершат работу. Для этого используется синхропримитив барьер. Когда процесс в своей программе выходит на оператор барьера, он блокируется до тех пор, пока все остальные процессы, указанные в этом операторе барьера, не выйдут на свои одноименные операторы барьера и не сообщат об этом в системных вызовах МОС. Зная из этих вызовов, какие именно процессы вписаны в данный барьер, МОС ожидает, когда последний из них выйдет на свой оператор барьера и сообщит об этом, а затем одновременно снимает все эти процессы с блокировки.
Синхронизация параллельных асинхронных вычислительных процессов. Метод семафоров.
В определенные интервалы времени несколько параллельных процессов могут одновременно затребовать один и тот же общий ресурс. Такие интервалы времени работы ВС называются критическими интервалами. Необходимо так упорядочить доступ процессов к разделяемым ресурсам, чтобы они не могли взаимно искажать результаты вычислений. Например, нельзя допускать, чтобы одновременно один процесс записывал информацию в массив данных, а другой считывал ее. Нужно приостановить второй процесс (заблокировать), до окончания процедур записи первого, иначе второй получит либо устаревшие, либо искаженные динамикой записи данные, т.е. требуется взаимная синхронизация процессов. Синхронизация асинхронных параллельных процессов – это приостановка (блокирование) процессов в критических интервалах времени до выполнения требуемых условий их продолжения и свершения необходимой совокупности событий.
Для синхронизации применяются специальные синхропримитивы: 1) семафоры; 2) мониторы синхронизации; 3) критические секции (интервалы), которые сейчас введены в языки программирования, например оператор» событие» в PL/1, операторыDelay(задержка) иCond(Continue) (продолжение) в языке Паскаль. В многозадачной ОСWindowsNTдля этого используются специальные системные функции:
-« WaitForSingleObject«(WFSO) – ждать сигнал об обьекте «событие»;»hMutex- мьютекс взаимоисключения доступа.
В основе всех этих синхропримитивов лежит механизм семафоров, введенный в программирование ЭВМ известным американским ученым Дейкстра в 1968 году. Ранее на аппаратном уровне в устройствах управления процессорами подобный механизм был применен в отечественных ЭВМ: БЭСМ6 и Эльбрус 1.
Семафор Дейсктра- это неотрицательная целочисленная переменная, сохраняемая в специальной ячейке памяти и соответствующая одному какому-нибудь общему ресурсу. Процесс прежде, чем получить доступ к этому ресурсу, должен обратиться к ячейке семафора и выполнить над его значением SоперациюP(passeren- пропустить):P(S)=S-1, аналогом которой в современных языках является операторWAITX( ждать событие). Затем проверяется новое значение семафораS:=S-1. ЕслиS>0, то операцияPсчитается завершенной и процесс допускается к ресурсу, или безостановочно продолжает свою работу. ЕслиS=0, то операцияPсчитается незавершенной до тех пор, пока с помощью дополнительной операцииV, выполняемой другим процессом, значениеSне станет больше нуля, а до этого момента времени первый процесс, выполнившийP(S), приостанавливается (блокируется по семафоруS), а его идентификатор помещается в очередь к ресурсу на ожидание разблокирования.
Операция V(Vrygehen-освободить) увеличивает значения семафора:V(S) =S+1 и тем самым инициирует дозавершение одной из незавершенных операцийP. т.е. в итоге разблокирует один из приостановленных по семафоруSпроцессов с учетом дисциплины обслуживания очереди семафора к ресурсу (поFIFOили по приоритету).
Итак, операции P(S) иV(S) вводятся в два разных процесса и, если один из них приS=0 блокируется, выполнивP(S), то его разблокировать может только другой процесс после выполнения своей операцииV(S) над этим же семафоромS.
В ОС Windowsимеются специальные функции семафорного механизма:
- HANDLECreateSemaphore(параметры)- функция создания семафора;
-HANDLEOpenSemaphore(параметры)- функция открытия семафора с тем же именем;
-BOOLReleaseSemaphore(параметры)- функция увеличения счетчика, как аналог операцииV(x);
-WaitForSingleObject-функция ожидания переключения семафора;
-WaitForMultipleObject- функция уменьшения счетчика, как аналог операцииP(x).
Аппарат «событий», используемый в современных алгоритмических языках, по сути, является семафорным механизмом. Для работы с переменной Х типа «событие» используются следующие операторы:
WAITX(ждать событие Х- аналогP(X)),
SINGNALX(объявить событие Х- аналогV(x), в некоторых языкахSIGNALX=POSTX, илиTESTX, где Х-код события).
Оператор WAITзадерживает выполнение своего процесса, если событие Х не произошло. Оператор POST, вписанный в программу другого процесса, проверяет событие Х и, если оно произошло, разблокирует по этому событию Х первый процесс.
В ОС Windowsимеются специальные функции для синхронизации с помощью механизма событий:
-HANDLECreateEvent(параметры)- функция создания события;
-HANDLEOpenEvent(параметры)- функция открытия идентификатора события;
-BOOLSetEvent(HANDLEHEvent)- установка события (перевод в отмеченное состояние);
-BOOLResetEvet(HANDLEHEvent)- сброс события (перевод в неотмеченное состояние);
-BOOLPulseEvent(HANDLEHEvent)- функция пульсирующей установки с последующим сбросом события. Она возвращает управление, как только хотя бы одна задача, ожидающая это событие, перейдет в активное состояние. Мьютексы, широко используемые в ОСUNIXиWindowsдля синхронизации параллельных потоков процессов с целью защиты общей переменной путем взаимоисключения, - это простейшие двоичные семафоры (открыт, или закрыт), не требующие выполнения операцийP-декремента иV-инкремента, устанавливаемые и снимаемые ядром ОС по системному выводу:hMutex.
В ОС Windowsимеются специальные функции механизма мьютексов:
-HANDLECreateMutex(параметры)- функция создания объектаMutex;
-HANDLEOpenMutex( параметры)- функция открытия объектаMutexс тем же именем в другом процессе;
-Wait For Single Object (H Mutex)-функция завладения мьютексом;
-BOOLReleaseMutex(HANDLEHMutex)-функция освобождения объекта после завершения критического интервала ( секции), закрывавшегося по взаимоисключению;
-CloseHandle-полное уничтожение мьютекса путем закрытия идентификатора.
Рассмотрим конкретные примеры задания отношения предшествования и взаимоисключения процессов с помощью операций P(S) иV(S) над семафорамиS.
Прежде, чем рассматривать примеры уточним правило Дейсктра. По изначальному его правилу возникает неоднозначность, когда старые значения семафора равны 1или 0. Если S=0,то выполнениеP(S)=S-1 бессмысленно, так как отрицательные значенияS<0 не предусмотрены. Кроме этого, процесс выполнившийP(1)=1-1=0, должен быть заблокирован. Тогда возникает вопрос: как отличить эти два случая.
Неоднозначность легко устранима.
Достаточно в дополнение к основному правилу Дейсктра ввести следующее правило, не противоречащее ему:
- если S=1, то семафор открыт и процесс, выполнившийP(S)=P(1)=1-1=0, не блокируется, а новым значением семафораS=0 он закрывает доступ, или возможность продолжения, другим процессам;
-если S=0, то семафор закрыт процессу поP(S) без выполнения декремента. Т.е процесс, содержащийP(S), блокируется без изменения значения семафораS=0 и может быть разблокирован только другим процессом, выполнившим операциюV(S).
Это правило, называется синхронизацией по взаимоисключению и может применяться и без выполнения операций PиV, путем принудительного закрытия и открытия семафора операционной системой по соответствующему системному вызову, как при использовании мьютексов.
Отношение предшествования между процессами можно отобразить на графе, вершины которого соответствуют процессам, направленные дуги показывают очередность их исполнения, а расположение вершин по ярусам (уровням) дополнительно фиксирует требуемую последовательность передачи управления.

Дугам присваиваются имена разных семафоров. Здесь необходимы 3 семафора. Процессы P1 иP2 никогда не блокируются. ПроцессP3 блокируется до тех пор, пока оба входных процесса иP1, иP2 не завершаются и не открывают два семафораS13 иS23 на входе процессаP3. ПроцессP4 блокируется до завершенияP3 и открытия семафораS34. Эту очередность исполнения, или допуска к общему ресурсу, можно задать, если в текстах программ П1,П2,П3,П4 этих процессов правильно расставить синхрооператорыPиVи выбрать подходящие начальные значения семафоров
![]()
P1: П1;V (S13)
P2: П2;V (S23)
P3: P(S13), P(S23); П3; V(S34)
P4:P(S34) ; П4
Вначале семафоры закрыты для всех процессов. Поэтому любые попытки процессов P3 иP4 нарушить очередность будут « пресекаться», т.е. они будут заблокированы по семафорам, приостановлены с помещением их идентификаторов в очереди и будут ожидать разблокирования до тех пор, пока их последовательно не разблокируют другие процессы- вначале П1 и П2, а затем после завершения П3 своей заключительной операциейV(S34)=0+1=1 разблокирует последний процесс в цепи П4.
Если же очередность попыток запуска, или доступа, процессов будет правильной, то вначале закрытые семафоры будут поочередно открываться – вначале - для P3 после завершенияP1 иP2, а затем-дляP4 после завершенияP3.
Взаимоисключение процессов необходимо при обмене данными через почтовый ящик (буфер обмена). Пусть в нем имеется конечное число мест Smдля хранения сообщения стандартного формата, А- процесс- писатель, В-процесс-читатель

Правила работы с почтовым ящиком:
-процесс –писатель А блокируется, если читатель В считывает сообщение и если буфер переполнен;
-процесс-читатель В блокируется, если писатель А записывает новое сообщение и если буфер пустой.
Введем три семафора:
семафор писателя S1- число сводных мест в буфере, гдеS1≤Sm;
семафор читателя S2- число занятых мест в буфере, гдеS2≤Sm;
семафор взаимоисключения S3 {1,0}.
Тогда правила работы с почтовым ящиком можно реализовать путем правильного внесения операторов синхронизации PиVв тексты процедур обращения в буфер обмена.
Процесс- писатель А должен выполнить следующую последовательность операций:
P(S1),P(S3); записать сообщение;V(S2),V(S3), а процесс- читательB:
P(S2),P(S3); считать сообщение ;V(S1),V(S3).
Если число свободных мест S1=0, т.е. буфер заполнен, то писатель блокируется поP(S1) до тех пор, пока читатель не прочитает хотя бы одно сообщение и своей заключительной операциейV(S1) приS1=1 не разблокирует его.
Если буфер пустой S2=0, то читатель блокируется поP(S2) до тех пор, пока писатель не запишет хотя бы одно сообщение и своей заключительной операциейV(S2) приS2=1 не разблокирует его.
Одновременное обращение в буфере
обмена писателя и читателя невозможно,
так как при начальном значение семафора
любой из них, заходя в буфер, закрывает
за собой семафор операциейP(S3)=1-1=0,и
ни читатель, ни другой писатель уже не
сможет обратиться в буфер до тех пор,
пока не будет выполнена заключительная
операцияV(S3)=0+1=1.
Средства синхронизации в мультипроцессорах и мультикомпьютерах.
В мультипроцессорах с целью повышения надежности механизма взаимоисключения процессов в языки параллельного программирования введены условные критические интервалы (критические секции). Критический интервал связан с конкретным общим разделяемым ресурсом, например массивом данных. Вход и выход процесса в критических интервалах можно организовать аналогично взаимоисключению при работе с почтовым ящиком с помощью операций PиVнад семафорами. Уловный критический интервал (секция) отличается от семафоров тем, что вход в интервал разрешается каким – либо логическим условием, например:
REGION A IFL THEN BEGIN S1, S2,….Sn END,
где A- имя общего ресурса;
L- логическое выражение;
S1,S2,….Sn- последовательность операторов, выполняемых над общим ресурсомAв критическом интервале.
Если выражение Lистинно, то процесс с такой записью входит в интервал. АргументыL
определяются состояниями занятости и т.п. условиями, вроде правил работы с почтовым ящиком.
Если же ресурс Aзанят кем- то, то во всех процессах выражениеLбудетFALSH. Только при освобождении ресурса процесс своим заключительным указателемENDчерез выраженияLоткрывает доступ к ресурсу другим процессам. Этот механизм более универсален, чем семафоры, так как логическими выражениями можно ввести любые условия и виды синхронизации, а не только взаимоисключение.
Еще большей универсальностью обладают мониторы и управляющие выражения. Например, они позволяют запрограммировать отношения предшествования между процессами. Запись управляющего выражения:
PATHp;q; rENDзадает строгую очередность выполнения процессов: вначалеP, затем обязательно q и только послеq-r. Запись управляющего выраженияPATHN: (1:(p); 1:(q))ENDзначит, что должны быть автоматически настроены семафоры, не допускающие одновременного выполнения процессовpиq, а также ограничивающее число раз инициализации первого процессаpпо сравнению со следующим в очередности процессомqне более, чем наNраз больше.
В мультикомпьютерах механизм синхронизации неотъемлим от механизма организации передачи сообщений между процессами. Нам уже известен оператор
WHENL, с помощью которого можно логическим выражениемLзапрограммировать условия приема сообщения по оператору приемаRECEIVE. Известен также операторAWAITL(<выражение-приоритет>), по которому при ложности логического выраженияLсообщение ставится в приоритетную очередь на прием с учетом значения приоритета. В дополнение к операторамAWAITиACCEPT( вызов удаленной процедуры) при программировании коммуникаций применяется особый оператор синхронизацииSELECT, который позволяет программировать булевские выражения, устанавливающие очередность нескольких передач и/или вызовов процедур в зависимости от свершения заданного множества событий. Он применяется тогда, когда в процесс необходимо вводить по несколько операторовAWAITи/илиACCEPTи к ним создавать очереди. Рассмотренные операторы синхронизации основаны на механизме событий, идеология которого алогична семафорам. Кроме того семафоры используются в их утилитах. Они реализуется специальными подпрограммами МОС, которые также широко используют операторыWAIT( ждать) иPOST(объявить событие), принципы действия которых подобны функционированию операцийPиVнад семафорами.
Тупики в распределений ресурсов между параллельными процессами.
Тупики (клинчи, дедлоки, мертвые объятия) возникают в тех случаях, когда группа процессов захватывает ресурсы таким образом, что ни один из процессов не может быть завершен. Здесь ресурс имеет широкий смысл: процессор, модуль памяти, процессор ввода-вывода, файл, массив, запись, программа.
Главная причина возникновения тупиков - взаимная блокировка процессов при их синхронизации. Тупик - это непрекращающиеся взаимное ожидание разблокирования двумя и более заблокированными процессами.
Самый простой пример тупиковой ситуации - это такое состояние, когда два процесса монопольно владеют каждый своим ресурсом, но для завершения каждому из них требуется еще дополнительное число единиц ресурса, находящемся в монопольном владение другого.
Применяются три основных подхода в борьбе с тупиками:
- предотвращение;
-недопущение;
-обнаружение.
Они применяются и в мультипроцессорах, и в мультикомпьютерах, но в каждом из этих типов ВС имеют свою специфику.
Методы борьбы с тупиками в мультипроцессорах аналогичны применяемым методам в однопроцессорных мультипрограммных ЭВМ. Отличие состоит лишь в том, что в последней происходит полная остановка обработки, а в первых часть параллельных процессов может оказаться в тупике, а остальные могут восполняться.
А. Предотвращение тупиков.
Применяются 3 способа:
- прерывание одного из процессов;
-запрос всех требуемых ресурсов одновременно при запуске всех процессов;
-упорядочивание запросов ресурсов.
По первому способу, если процесс запрашивает ресурсы, занятые в этот момент времени, то он прерывается и у него отнимаются все ресурсы, которыми он владел. К сожалению, это приводит к слишком частому снятию процессов с решения, так как конфликты за ресурсы в параллельных ВС неизбежны.
Второй сейчас широко применяется и основан на том, что планировщик в статике заранее распределяет все ресурсы между процессами и закрепляет их за процессами до их завершения. Однако у него имеются два существенных недостатка: а) неэффективно используются ресурсы, так как они заблокированы для других процессов до тех пор, пока не будет выполнен процесс, их захвативший; б) время ожидания другими процессами занятых ресурсов оказывается чрезмерно большим.
По третьему способу все ресурсы разбиваются на классы. Каждому классу присваивается номер. Процессу разрешается в динамике запрашивать только тот новый ресурс, номер которого выше номеров классов ресурсов, которыми процесс уже владеет. К сожалению этот способ резко ограничивает возможные последовательности запросов на ресурсы, что также приводит к большим временам ожидания освобождения требуемого по последовательности номеров ресурса.
Б. Недопущение тупиков.
Этот метод борьбы с тупиками применяется в динамике исполнения совокупности процессов. Ресурс представляется процессу только в том случае, если после этого остается хотя бы один путь завершения всех начатых процессов.
Хорошо известна стратегия максимальных требований, положенная в основу эвристического «алгоритма банкира» для динамического распределения и перераспределения ресурсов.
По каждому запросу у мультисистемной ОС каждым из процессов определенного числа единиц какого- либо ресурса вызывается программный модуль «Планировщик», который, как банкир, учитывая, сколько единиц этого ресурса уже занято и сколько будет освобождено уже начатыми старыми процессами после их завершения, оценивает, хватит ли этого ресурса и уже начатым старым, и новому процессу, до их окончания, если допустить к ресурсу новый процесс. При этом используется механизм динамических приоритетов. По ходу названной оценки все процессы ранжируются заново и создается новая системная таблица уровней их приоритетов. Процессы, освобождающие наибольшее число единиц ресурса по завершении, получают высшие уровни приоритетов, а новый процесс - низший уровень. Если в результате нового ранжирования решение положительное, то старая таблица приоритетов заменяется новой, а новый процесс, запросивший ресурс, допускается в приоритетную очередь ожидания доступа к данному ресурсу с низшим уровнем приоритета. Если же решение отрицательное, т.е. ресурса не хватит для совместного завершения старых и нового процесса, последний блокируется семафором до освобождения ресурса одним из старых процессов, который своей заключительной операцией V(S) разблокирует его и допустит к очередной попытке участия в алгоритме банкира. Естественно, в последнем случае сохраняется старая таблица уровней приоритетов старых процессов.
Недостатки очевидны: 1) большие расходы машинного времени, так как нужно обрабатывать каждый запрос на каждый ресурс каждого процесса; 2) необходимость иметь в памяти «Планировщика» априорную информацию о будущих потребностях всех процессов во всех видах ресурсов.
В. Обнаружение тупиков.
Применяется следующая стратегия распределения ресурсов. В динамике все требования на ресурсы удовлетворяются. По крайней мере любой процесс допускается в очередь на захват требуемого ресурса. Периодически включается алгоритм, проверяющей состояние системы на наличие тупика. При обнаружение тупика принимаются меры к выводу системы из тупика.
Для распознавания тупиков применяется графовая модель Холта, моделирующая динамику использования ресурсов процессами. Граф ресурсов содержит раскрашенные узлы, соответствующие процессам и ресурсам. Граф динамический и в промежутках между проверками постоянно модифицируется в памяти планировщика. Раскрашенные вершины графа и его дуги кодируются и хранятся в системной таблице. Для пояснения принципа отобразим графически раскраску вершин: процесс обозначим квадратом, а ресурсы кружком. Ресурс-кружок взвесим числом имеющихся в системе единиц данного ресурса. Дуга, ведущая из процесса в ресурс называется дугой требований и соответствует запросу одной единицы этого ресурса. Дуга, ведущая из ресурса в процесс, означает выделение одной единицы ресурса этому процессу. Число дуг, исходящих из ресурса к различным процессам, не может превышать веса вершины-ресурса, т.е. имеющегося числа единиц этого ресурса. Мгновенное состояние использования ресурсов можно отобразить следующим графом ресурсов.

Процесс Р1 требует 2 единицы ресурса R1 и одну единицу ресурсаR2.
Процесс P2 требует 1единицу ресурсаR2. ПроцессуP2 уже выделены 2 единицы ресурсаR1. Граф динамический и в каждом шаге проверки системы может быть разным.
Проверка состояния системы на тупик выполняется путем специального преобразования графа ресурсов Холта - редуцирования графа. При редуцировании процессы разделяются на заблокированные и незаблокированные.
Процесс считается заблокированным, если число его дуг требований какого- либо ресурса (исходящих из процесса дуг) превышает число свободныхединиц этого ресурса. Например, на графе процессP1 заблокирован по ресурсуR1, так как он требует 2 единицы ресурсаR1, а осталась свободной лишь одна единица, так как 2 единицы уже захвачены другим процессомP2.
Процесс находится в тупике, если его нельзя вывести из состояния блокирования.
Метод редукции графа ресурсов Холта состоит в следующем. Для каждого незаблокированного процесса, например на нашем графе P2 (он получает и ресурсR1, и ресурсR2, так какP1 заблокирован), нужно убрать в графе и таблицах его описания все входящие и исходящие дуги.
Граф называется полностью редуцированным, если после редукции (исключении дуг незаблокированных процессов) он не содержит ни одной дуги. В этом случае запросы на ресурсы всех процессов могут быть удовлетворенны. Если после редуцирования останется хотя бы одна дуга, то обнаруживается возможность возникновения тупика.
Этот алгоритм, в отличие от алгоритма банкира не способен гарантировать недопущение тупика, а лишь его обнаруживает.
Для выхода из тупика применяются следующие дополнительные методы:
процессы, попавшие в тупик, оставшиеся с дугами после редуцирования графа ресурсов, последовательно удаляются, начиная с наиболее «жадного» с максимальным числом дуг, до тех пор, пока в редуцированном графе исчезнут все дуги. Удаленные процессы ставятся в очередь и по завершению хотя бы одного процесса из не- удаленных в очередном шаге проверки при нулевом редуцировании добавляются по одному в граф ресурсов и вновь редуцируют. Если повторное редуцирование покажет отсутствие дуг, процесс допускается в очереди к ресурсам;
у процессов, незаблокированных и ненаходящихся в тупике, отнимают часть ресурсов и ставят их в очереди, а отнятые ресурсы передают заблокированным процессам. Дуги требований пострадавших процессов аналогично предыдущему постепенно в очередной шаг редуцирования вводятся в граф ресурсов и повторным его редуцированием выясняется допустимость возврата отнятых ресурсов пострадавшим процессам.
В мультикомпьютерах обнаружение тупиковых ситуаций вызывает дополнительные трудности. Процессорные блоки системы, в том числе ведущий процессор, могут не обнаружить тупик из–за сравнительно больших коммуникационных задержек, так как любой из них при анализе состояния с распределением ресурсов основывается на имеющейся в нем информации к моменту выполнения алгоритма обнаружения. Он либо не успеет получить нужную информацию и из-за этого пропустит угрозу тупика, либо вообще не получит никаких сообщений из тупиковых областей системы.
Поэтому в мультикомпьютерах не применяется недопущение тупиков из-за больших потерь машинного времени на пересылку сообщений о числе занятых единиц ресурсов, требуемых для алгоритма банкира. В основном применяются предотвращение тупиков путем заблаговременной раздачи процессам всех требуемых им ресурсов и обнаружение тупиков в динамике выполнения процессов.
Алгоритмы обнаружения, основанные на централизованном сборе информации о состоянии с ресурсами во всей системе, также не применяются из-за больших коммуникационных задержек. Обычно применяются методы обнаружения, основанные на децентрализованном анализе тупиковых ситуаций.
Классическим методом является обнаружение тупиков по виду динамически модифицируемого графа ожидания транзакций(TWF). Он учитывает и графически отображает как состояние распределения ресурсов, так и процесс передачи сообщений между узлами топологии коммуникационной среды, т.е. между процессорными блоками, расположенными в этих узлах.Транзакция- это последовательность операций над информацией, которая переводит систему из одного состояния в другое.
Процесс, обслуживающий транзакцию, во время выполнения действий с ресурсом не взаимодействует по управлению с другими процессами, а во время транзакции не может изменить свой алгоритм. Он может изменить его только самостоятельно и только в интервале между двумя соседними транзакциями.
Транзакция может находиться в активном состоянии или в состоянии блокировки. В последнем случае необходимый ей ресурс используется другой транзакцией.
Граф ожидания транзакций (TWF) отображает состояния всех транзакций в системе. Каждая вершина графаTWFпомечается двумя именами: именем транзакцииTiи именем узла топологии коммуникационной среды мультикомпьютераSj.
Граф TWFсроится следующим образом:
Из точки (Ti,S) в точку (Tj,S), где (Ti,Tj) - имена разных транзакций;S- имя данного узла; проводится направленная дуга, если транзакцияTiблокирована в узлеSи ожидает в этом же узлеSдо тех пор, пока другая транзакцияTjв этом же узлеSне освободит занятый ею ресурс, требуемый заблокированной транзакцииTi.
Из точки (T,Si) в точку (T,Sj) проводится направленная дуга, если транзакцияTзаблокирована в узлеSiи ожидает сообщения от такой же транзакции (или в этой же транзакции) из другого узлаSj. Рассмотрим простой пример, когда в системе имеется только два узла, обменивающихся сообщениями.

Необходимым и достаточным условием для возникновения тупика является наличие цикла с однонаправленными дугами. В примере имеются два таких цикла: один локальный в узле S2, другой глобальный, связанный с ресурсами обоих узлов. Например, в локальном цикле в узлеS2 5-я транзакция ожидает освобождения ресурсов 6-ой транзакцией, 6-я ожидает 3-ю, а 3-я ожидает 5-ю. Следовательно, образовалась замкнутая цепь бесконечных взаимных ожиданий разблокирования по освобождению ресурсов.
Такой граф нужно обновлять в памяти ведущей ЭВМ каждый раз, когда транзакция переходит из активного состояния в блокированное и наоборот.
Вывести систему из тупика можно путем прерывания некоторых транзакций с целью разрыва циклов в графе TWF. Критерий выбора транзакции, подлежащей прерыванию, - минимизация потерь, вызванных прерыванием.
Управление параллельными процессами в ОС UNIX и Windows NT.
Современные операционные системы UNIXиWindowsпоследних модификаций (Posix,Solaris,LinuxиNT) содержат системные вызовы для порождения, отслеживания и завершения параллельных процессов, в том числе распределения ресурсов, синхронизации и организации взаимодействия между ними как через общую память, так и путем передачи сообщений. Они поддерживают параллелизм, как между процессами, так и в пределах одного сложного процесса с использованием нескольких потоков и нитей.
В ядре ОС UNIXимеется специальная структура управления процессами, которая выполняет следующие основные функции:
-управление межпроцессорной связью;
-синхронизация процессов;
- планирование работы процессов, основанное на приоритетных очередях;
- управление памятью, в том числе поддержка виртуальной памяти с возможностью разделения (совместного использования) общих областей и адресного пространства несколькими процессами.
По системному вызову forkв системеUNIXв любой момент можно создать точную копию основного процесса. Исходный процесс называется порождающим, а новый - порожденным процессом. Они идентичны и разделяют одни и те же файловые дескрипторы. Но эти два процесса могут выполнять свою работу независимо друг от друга. Порожденный процесс можно модифицировать через системный вызовexec. Этот вызов позволяет заместить программу и данные в порожденном процессе по его вызову, взяв их из выполняемого файла, адресуемого специальным параметром в вызовеexec. Если порождающий процесс необходимо заблокировать до тех пор, пока порожденный завершит свою работу, то в требуемом месте программы первого процесса вписывается системный вызов синхронизацииwait, по которому он приостанавливается, а для его разблокирования в конец программы второго процесса необходимо вписать системный вызовexit.
Процессы могут инициировать системный вызов forkсколько угодно раз, в том числе и порожденные, а применяя вызовexecможно сформировать дерево новых процессов.

В UNIXприменяется два способа организации взаимодействия процессов друг с другом:
- через специальную информационную структуру, называемую каналом, являющуюся буфером обмена типа почтового ящика со строго детерминированным порядком записи- чтения, когда данные приемник может получить только в том порядке, как они записаны в буфере источником;
- приоритетная очередь сообщений, которая заполняется по системному вызову «отправить сообщение», а освобождается по вызову «получить сообщение»; в очереди сохраняются границы между разными сообщениями, а срочные сообщения по их приоритету приемник получает в первую очередь.
Кроме этого имеются специальные системные вызовы организации в мультикомпьютерах взаимодействия через виртуальную распределенную совместно используемую память (DSM):
-синхронизованный почтовый ящик для обмена страницами;
-разделяемая несколькими процессами общая область их виртуальных адресных пространств, позволяющая видеть им всем запись, сделанную в эту общую область любым из взаимодействующих процессов.
Система UNIXможет поддерживать несколько параллельных потоков управления в одном и том же адресном пространстве в пределах одного и того же процесса. Они называются упрощенно потоками. Каждый поток имеет свой счетчик команд, свои отдельные регистры и стек. Потоки разделяют все объекты и ресурсы основного процесса. Каждый из потоков может приостанавливаться для синхронизации. Они могут обмениваться информацией через общий сегмент памяти, как через буфер.
Потоками можно управлять как со стороны ядра ОС, так и со стороны прикладного процесса. Например, в версии Posixимеется 11 системных вызовов для создания, отслеживания, синхронизации и завершения потоков.
Для синхронизации потоков применяется два синхропримитива:
- мьютексы - это двоичные семафоры для кратковременной блокировки, например чаще всего для защиты общей переменной путем взаимоисключения;
-переменные условия для длительных блокировок, когда разблокирующий процесс по завершению работы с защищаемым ресурсом образует специальную переменную, аналогично операции V(S) над семафором.
Управление параллельными процессами в ОС WindowsNTотличается от ОСUNIX, тем, что новые процессы создаются не копированием с последующей модификацией, а с помощью специальной функцииCreateProcess, которая требует указать для каждого нового процесса значения 10 параметров: имя; указатели на дескрипторы защиты, флаги, каталоги, строку описания конфигурации; командную строку и т.п. Все процессы равны по подчиненности, однако имеется специальный указатель на структуру для организации взаимодействия с вызывающей процедурой.
Диспетчер процессов и потоков позволяет создавать, удалять и поддерживать несколько взаимодействующих и синхронизуемых процессов. В любом процессе можно создать несколько параллельных потоков, а в любом потоке - несколько нитей. Вначале процесс создается с одним потоком, аналогичным потоку Unix, но в дальнейшим процесс может создать еще несколько потоков. Потоки создаются ядром ОС по специальному вызову с указанием 6-ти создающих параметров. Можно управлять потоками в любом процессе из другого процесса, используя системные вызовы функций ядра ОС.
В каждом потоке можно создать несколько параллельных нитей (fibers). Они похожи на потоки, но создается пользователем с организацией их взаимодействия и синхронизации по операторам прикладных программ.
Взаимодействие процессов осуществляется следующими способами: через каналы, именованные каналами сетей ЭВМ; почтовые ящики, сокеты, удаленные вызовы процедур, общие файлы.
Каналы двухсторонние (дуплексные):
-байтовые, не сохраняющие границы между сообщениями;
-каналы сообщений, сохраняющие границы между сообщениями и не сливающие их в одно длинное.
Сокеты - те же каналы, связывающие разные процессы на разных ЭВМ и чаще всего во взаимодействии с именованными каналами.
Общая виртуальная память разделяется путем отображения данных в один и тот же файл. Все записи, выполненные одним из процессов, появляются в виртуальных адресных пространствах других процессов. Можно создать почтовый ящик, используемый для обмена страницами.
В WindowsNTприменяются 4-ре механизма синхронизации параллельных процессов: семафоры, мьютексы, критические секции (интервалы), уже хорошо нам известные, а также события. Однако блокируются не сами процессы, а их потоки, причем независимо друг от друга, т.е. взаимно блокируются потоки разных процессов по системным вызовам функций ядра ОС.
Для повышения надежности механизма семафоров введена функция ограничения времени простоя заблокированного потока, когда по истечении тайм- аута даже при закрытом семафоре поток разблокируется ядром ОС и допускается к защищаемому ресурсу. Если из-за сбоя в семафорном механизме какой-то процесс слишком долго не разблокируется, то по тайм-ауту он все-таки разблокируется и, если нет условий для его повторного блокирования, получит доступ к ресурсу и продолжится.
Критические секции (интервалы) управляются не ядром ОС, а прикладными программами и применяются для синхронизации нитей. Они работают быстрее, чем простейшие мьютексы, так как не требуют выполнения системных вызовов.
События - это механизм ядра ОС, который вызывается из потока, если ему необходимо приостановиться и дождаться какого- либо события, оговоренного в параметрах вызова. Разблокирование выполняется ядром ОС, если описанное в параметрах вызова событие свершилось.
Мультисистемные ОС (МОС) развиваются от наиболее простых вариантов их функциональной организации: 1) ведущий- ведомый (ОС UNIX); 2) с раздельным выполнением заданий и равноправными процессами в каждом из процессоров (ОСWindowsNT); до наиболее сложного и полного варианта, удовлетворяющего всем описанным в п.4.1.1-4.1.4 требованиям и функциональным возможностям, так называемого метода: 3) симметричной (однородной) обработки. В нем наиболее полно соблюдается принцип независимости между программами и процессорами, причем и прикладными, и системными программами. Широко используется механизм множества приоритетных очередей ко всем ресурсам, в том числе и процессорам. Обеспечивается возможность параллельной обработки системных программ МОС путем вытеснения из процессоров прикладных программ в критические интервалы обработки множества системных вызовов от прикладных процессов.
4.2 Параллелизм на уровне прикладного программирования
4.2.1 Системы и языки параллельного программирования.
Рассмотрим особенности параллельного программирования многопроцессорных ВС по сравнению с программированием однопроцессорных ЭВМ. В настоящие время создано достаточно много алгоритмических языков параллельного программирования:
- параллельные Паскаль, PL/1,C, Ада для мультипроцессоров;
-ОВС - Фортран, PVW,MPI,Linda,Orca,Globeдля мультикомпьютеров;
-ОССАМ (ОККАМ) для транспьютерных сетей.
Система параллельного программирования включает следующие средства:
1) языки параллельного программирования для написания подпрограмм фрагментов, полученных после декомпозиции исходной программы, которые позволяют вводить операторы взаимодействия и синхронизации фрагментов и организации отказоустойчивых вычислений;
2) интерактивные полуавтоматические трансляторы и компиляторы, позволяющие автоматизировать распараллеливание последовательных программ и алгоритмов;
3) средства отладки параллельных программ: экранный редактор, синтаксический анализатор, средства структурного редактирования;
4) программы для оценки эффективности распараллеливания: ожидаемого ускорения и требуемой памяти.
Параллельные алгоритмические языки мультипроцессоров получают из их последовательных аналогов путем дополнения последних операторами организации взаимодействия и синхронизации последовательных фрагментов, выполняемых в разных процессорах, через общие переменные и почтовые ящики в общей памяти. Используются также системные вызовы этих функций, реализуемых ядром операционной системы. Названных выше языков, их компиляторов и современных многозадачных ОС UNIX,LinuxиWindowsNTдостаточно для организации параллельных вычислений на мультипроцессорах с общей памятью.
В мультикомпьютерах названных средств недостаточно. Последовательное программирование каждого из процессорных блоков традиционное. Операционные системы UNIX,LinuxиWindowsNTпозволяют управлять параллельными процессами в мультикомпьютерах. Однако для организации взаимодействия между процессами путем передачи сообщений требуется дополнительное связное программное обеспечение, которое принято называть системой параллельного программирования мультикомпьютеров.
Первая система программирования однородных мультикомпьютеров была создана в 50-х годах прошлого века в Сибирском отделение РАН путем расширения языка Фортран. Он был дополнен операторами группового и индивидуального взаимодействия, реализуемыми специальными автономными подпрограммами. Эти подпрограммы были сведены в библиотеку системных операторов, загружаемую резидентно в ЛОП каждого процессорного блока. В текстах программ блоков они вызывались известным оператором вызова CALL…(кол). Исполнительные процедуры организации взаимодействия: проверка условий синхронизации, адресная маршрутизация, прокладка логического канала связи выполнялись специальными функциями ядра МОС на основании системных вызовов и сообщений процессов из ведомых процессорных блоков.
Например, при организации какого- либо вида группового взаимодействия из семи возможных:
- трансляционный обмен;
- дифференцированный обмен;
- конвейерно-параллельный обмен;
- коллекторный обмен;
-трансляционно-циклический обмен;
- обобщенный условный переход;
-групповая синхронизация;
оператор, задающий вид взаимодействия, вписывался в тексты программ всех процессорных блоков, участвующих в данном взаимодействии. Взаимодействие организовалось ядром МОС только после того, когда все названные параллельные фрагменты выйдут на этот оператор и каждый из них сделает системный вызов. В параметрах этих вызовов указываются номера всех фрагментов (процессов), которые участвуют в данном взаимодействии. Когда последний из них сделает системный вызов, МОС берет управление на себя, выполняет адресную маршрутизацию, прокладывает логические каналы связи между процессорами в соответствии со значениями параметров и именем вида взаимодействия, а затем передает управление локальным взаимодействующим процессам. После этого они пересылают друг другу заданные в операторе сегменты массивов данных. Рассмотренный способ организации группового взаимодействия основан на барьерной синхронизации. В настоящие время созданы аналогичные, более совершенные системы параллельного связного программирования мультикомпьютеров: системы PVWиMPI.
4.2.2. Системы параллельного программирования мультикомпьютеров.
Связное программное обеспечение мультикомпьютеров (MPPиCOW) основано на библиотеках подпрограмм и примитивахsendиreceive. Можно запрограммировать три варианта организации передачи сообщений: синхронная, буферная и неблокируемая передача.
При синхронной передаче отправитель сообщения, выполнивший операцию send, блокируется до тех пор, пока получатель не выполнит операциюreceive, примет сообщение и подтвердит прием.
При буферной передаче отправитель не блокируется и может выполнить несколько операций sendподряд, не требуя подтверждения приема по каждому сообщению. Тогда сообщения временно сохраняются в буфере до тех пор, пока получатель не возьмет их оттуда. Только после этого приемник выполнит операциюreceiveи подтвердит прием. Такой режим передачи применяется, если получатель не может прервать свою работу. Отправив сообщение, передатчик не имеет вначале никаких гарантий, что сообщение получено, но в конце-концов получает подтверждение.
При неблокируемой передаче отправитель вообще никогда не блокируется. Она применяется, если отправитель после системного вызова sendможет продолжать работу, не требуя немедленного ответа. В этом режиме передачи и ядро МОС может не спешить и обслуживает вызовsendпозднее, когда у него будет время. В этом режиме усложняется работа ядра МОС с буфером, так как возможно его переполнение неотправленными сообщениями. Поэтому МОС может блокировать отправителей из-за переполнения общего системного буфера сообщений.
В настоящие время широко применяются две следующие системы параллельного программирования мультикомпьютеров.
PVM(ParallelVirtualMachine) -виртуальная машина параллельного действия. В основном применяется для программирования кластеровCOWв сочетание сOCUNIX. Может использоваться и в массовопараллельных мультикомпьютерахMPP. Она управляет параллельными процессами и системой ввода-вывода. СистемаPVMсостоит из двух частей:
-библиотеки системных вызовов;
- «сторожевого» процесса, постоянно работающего на каждой ЭВМ мультикомпьютера.
При запуске PVMзадается конфигурация - какие именно машины должны входить в ее виртуальный компьютер. Она хранится в конфигурационном файле. Однако машины можно добавлять и исключать командами с консолиPVM. Во всех ЭВМ, включенных в конфигурацию, запускается «сторожевой» процесс. Имеется специальная команда запускаnпараллельных процессов. Размещение процессов по ЭВМ конфигурации выполняет автоматически системаPVM. С помощью параметров этой же команды пользователь может подменять процессы. Имеется специальная процедура для запуска процессов из любого работающего процесса.
Каждый процесс имеет один пересылочный буфер и один приемный буфер. Отправляя сообщение, процесс вызывает библиотечные процедуры. Они запаковывают данные в активный пересылочный буфер так, чтобы получатель мог бы их преобразовать в исходный формат. После компоновки сообщения отправитель вызывает процедуру pvm_send.
Получатель может использовать 3 вида библиотечных процедур приема:
Процедуру Pvm_recv, которая блокирует его до прихода подходящего сообщения. По завершению процедуры сообщение сохраняется в активном приемном буфере. Далее оно распаковывается и преобразуется в подходящий для приемника формат.
Процедуру Pvm_trecv, которая блокирует его на заданный промежуток времени, но разблокирует сразу по получении сообщения.
Процедуру pvm_nrecv, которая сразу же пытается выполнять прием и выдает либо принятое сообщение, либо признак его отсутствия. Системный вызов обычно повторяется несколько раз, чтобы не потерять входящие сообщения.
Имеются процедуры широковещания (Pvm_bcast) и мультивещания (Pvm_mcast). По первой сообщение отправляется всем процессам в названной их группе, а по второй рассылается по стеку адресов, указанных в параметрах.
Синхронизация параллельных процессов выполняется по процедуре Pvm_barrier. Процесс, вызвавший эту процедуру, блокируется до тех пор, пока заданное в параметрах число других процессов не вызовет эту же процедуру. Только самый поздний из них инициализирует снятие блокировки со всех процессов этой группы.
PVM- сложный программный комплекс, в котором имеются процедуры управления ведущей ЭВМ, группами машин, буферами, а также для проверки состояния.
Вторая, широко используемая система параллельного программирования мультикомпьютеров - это MPI(Message-PosingInterface),интерфейс с передачей сообщений. Она содержит намного больше библиотечных вызовов и параметров на каждый вызов по сравнению сPVM.
Процессы создаются пользователем с помощью ряда системных вызовов. При этом они организуются в группы, которые при обработке уже не изменяются.
Система MPIработает с языкамиFORTRAN,C,C++. Подпрограммы организации индивидуального и группового взаимодействия называются функциями. БиблиотекаMPIсодержит более 120-ти функций. Стандартизованы два интерфейса: интерфейс системы программирования и интерфейс пользователя. Поддерживаются две архитектуры:MIMD(MKMD) иSIMD(OKMD).
Функции MPIпозволяют выполнять следующие виды структурного и коммуникационного программирования:
- создавать коммуникаторы;
-выбирать подходящую операцию коммуникации;
-задавать типы передаваемых данных;
- составлять виртуальные топологии процессов.
Для каждой создаваемой группы процессов выделяется отдельная среда связи -коммуникатор. Каждый процесс имеет два атрибута:
имя коммуникатора и номер процесса в коммуникаторе. Коммуникатор- это группа процессов и контекст. Контекст- это метки процессов: идентификаторы спецификации или фазы выполнения. Коммуникаторы необходимы для программирования разных видов группового взаимодействия, например барьерной синхронизации. Тогда в каждый процесс группы нужно ввести функцию барьерной синхронизации:
IntMPIBarrier(MPIComm.comm), гдеcomm- идентификатор данного коммуникатора.
Эта функция блокирует работу вызвавших ее процессов до тех пор, пока все процессы данного коммуникатора comm., у которых он указан в качестве основного атрибута, не вызовут эту же барьерную функцию с тем же именем коммуникатораcomm.
MPI, используя коммуникаторы, поддерживает следующие виды группового взаимодействия: широковещание, распределение и сбор данных; обмен данными, например конвейерно-циклический; агрегация и барьерная синхронизация. Все процессы в группе (коммуникаторе) должны делать один и тот же вызов с совместимыми параметрами.
В MPIимеется очень большое количество функций организации индивидуального (парного) взаимодействия. Они введены с целью упрощения программирования условий взаимной синхронизации передатчика и приемника сообщений. В исторически первой отечественной системе ОВС - Фортран было всего два оператора индивидуального взаимодействия, но они сопровождались очень сложным паспортом событий, в котором под каждый вид взаимодействия приходилось программироватьвекторсемафоров. Причем, по каждому системному вызову приходилось пересылать от инициатора в ядро МОС в ведущую ЭВМ достаточно длинное описание паспорта, занимающее несколько слов данных.
В системе MPIпошли по другому пути увеличения числа функций, и учли все виды взаимной синхронизации приемника и передатчика в множестве разных способов организации их взаимодействия.
Все функции парного взаимодействия разделены на две группы:
- функции с блокировками (элементами синхронизации);
- функции без блокировки.
Функции первой группы поддерживают множество коммуникаций 4-х типов:
-синхронный, по которому отправитель не может начать передачу данных, пока получатель не вышлет вызывающую процедуру MPI-Recv;
-буферизированный, не требующий синхронизации по п.1;
- стандартный, реализуемый по желанию программиста либо как синхронный, либо как буферизированный;
- синхронный по готовности передатчика, но без проверки приемника, полагая, что программа составлена так, что приемник обязательно уже готов к приему сообщения.
Интересна функция приема MPI-Recv. Это прием сообщения от заданного в параметрах функции процесса- передатчика с блокировкой. Число элементов в принимаемом сообщение не должно превышать указанное в параметрах функции их число. Блокировка приемника выполняется до тех пор, пока все элементы сообщения оговоренного передатчика не будут приняты и записаны в указанный в параметрах функции буфер. Функции парного взаимодействия без блокировки выполняются асинхронно. Например, с помощью этих функций программист может выставлять асинхронный запрос на получение какого-либо сообщения от заданного процесса- отправителя, когда бы тот его не отправил. Возможно и обратное программирование асинхронной передачи сообщения заданному приемнику, независимо от того, когда он будет готов к приему и примет сообщение в свой входной буфер. Конечно, при этом требуется промежуточная буферизация сообщений. Чтобы при этом сообщения не накладывались в буфере друг на друга, можно в программу ввести дополнительные функции синхронизации использования буфера, указанного в основной функции приема- передачи, а именно:MPIWaitиMPITest, аналогичные семафору взаимного исключения в «почтовом ящике».
Наконец, в системе MPIимеются функции для программированиявиртуальных топологий процессов, т.е. связывания их друг с другом по топологиям: дерево, кольцо, решетка, гамак и т.п., причем независимо от реальной топологии аппаратных средств связи между процессами. Например, в дереве процессов значения передаются от листьев к корню, подвергаясь обработке в каждом узле дерева.
Кроме этого MPIпозволяет создавать динамические процессы, неблокирующую коллективную коммуникацию (широковещание), расширенную поддержку ввода- вывода и выполнять обработку в режиме реального времени.
В последние время в связи с внедрением кластерных ВС типа COWи метакомпьютеров переходят к более совершенным системам параллельного программирования, основанным на виртуальной распределенной совместно используемой памятиDSM(DistributedSharedMemory). Программисты предпочитают иллюзию общей памяти даже, если физически она не существует. Конечно, это потребовало сложных алгоритмов обеспечения когерентности страниц и привело увеличению коммуникационных задержек на их пересылки. Поэтому в современных системах программированияLinda,Orea,Globeпри создании виртуальныхDSMиспользуется более мелкие общие совместно используемые единицы информации: кортежи и объекты.
Например, система Globe, используемая при программировании метакомпьютеров, основана на виртуальнойDSMс общими объектами, создаваемой на прикладном уровне системы протоколовInternet. Объект может находиться в общем виртуальном адресном пространстве нескольких ЭВМ даже на разных континентах. Чтобы получить доступ к данным общего объекта, пользовательский процесс должен пройти через специальные процедуры объекта. Имеется возможность доступа только к одному экземпляру данных, часто обновляемых одним и тем же пользователем.
В тоже время можно все данные встраивать в каждую копию общего объекта, а для их обновления посылать сигналы каждой копии объекта по протоколу широковещания. Каждый объект может иметь собственную стратегию дублирования, обновления и защиты. Наиболее трудные вопросы - это размещение объектов по сети ЭВМ, управление ими и расширение системы. Разработчики системы Globeутверждают, что она может работать на миллиард пользователей и триллион объектов.
Рассмотренные примеры систем параллельного программирования мультикомпьютеров показывают, что универсальные системы программирования параллельных ВС общего назначения являются достаточно сложными и трудоемкими. Для достижения достаточно высокой степени загрузки множества процессоров требуется сравнительно длительный процесс адаптации параллельной программы путем составления и отладки нескольких вариантов программы и выбора того из них, на котором получается максимальная производительность. Такие трудозатраты оправданы при создании уникальных программных комплексов, например систем предсказания погоды или курсов валют, авиадиспетчерской, исследования человеческих генов, авиатренажера, управления космическими полетами, предсказания землетрясений и катастроф и.т.п.
При проблемной ориентации мультикомпьютеров на менее громоздкие, но широко распространенные в повседневной практике задачи можно было бы применить менее гибкую и универсальную, но значительно более простую и наглядную систему параллельного программирования Occam, созданную дляMPP- систем типа транспьютерных сетей.
4.2.3. Язык Оккам для программирования МРР - систем типа транспьютерных сетей
Язык Оккам (Occam) позволяет программисту представить сложную программу в виде множества параллельно и последовательно выполняемых процессов, взаимодействующих друг с другом посредством пересылки сообщений по каналам связи. Так как он разработан специально для транспьютерных сетей, в нем имеется целый ряд упрощений и ограничений:
-для каждого параллельного процесса используется обычно один транспьютер;
-поведение любого процесса определяется только сообщениями, проходящими по его каналам связи, т.е. процесс, приостанавливается (ожидает) до тех пор, пока по указанному входному каналу транспьютера или синхроннопо нескольким каналам не поступят требуемые для его продолжения входные значения оговоренных переменных;
- идентификаторы используемых каналов вводятся в программы процессов;
-число каналов одного процесса ограничено: не более четырех;
-ввод-вывод значений по каналам возможен только в паре синхронизованных по программе процессов, т.е. оба процесса по динамике исполнения программы должны быть готовы к взаимодействию и, если один выводит значение в выходной канал, другой, находясь в режиме ожидания, должен сразу же его вводить по своему входному каналу; обмен данными между процессами через каналы аналогичен обмену информацией между синхронно работающими устройствами;
-вывод значений, подлежащих передаче другим процессам, выполняется сразу же в назначенный выходной канал после их вычисления без дополнительной проверки готовности к их приему в других процессах, т.е. согласование синхронизации должно быть выполнено заранее при программировании и в этот момент обязательно должен иметься хотя бы один процесс, готовый к приему и ожидающий ввода входного значения; иными словами при программировании на Оккаме необходимо программно выполнить синхронизацию процессов перед программированием обмена информацией между ними;
- внутренняя структура процесса безразлична, т.е. его программа может быть составлена в традиционных языках последовательного программирования однопроцессорных ЭВМ и лишь обрамлена операторами языка Оккам. Кроме этого разработаны специальные интерпретаторы, загружаемые в каждый транспьютер и позволяющие писать внутренние программы процессов в примитивах и конструкцииях языка Оккам. Компилятор языка Оккам позволяет заменять параллельные конструкции на эквивалентное их последовательное выполнение на одном процессоре в режиме разделения времени.
Оккам- процесс определяется только следующими фазами работы:
начало;
обработка, при которой контролируются и выполняются только следующие процедуры:
2.1) присваивание- изменение значения переменной, в том числе, кроме присваивания ей значения констант или других переменных, ей может присваиваться код идентификатора канала связи;
2.2) ввод- получение значения из указанного входного канала связи;
2.3)вывод- засылка значения переменной в указанный выходной канал связи (возможен двунаправленный ввод-вывод на основе дуплексных каналов связи);
3) завершение процесса.
Все, что касается обработки информации, то это возлагается на внутренние структуры процессов и учитывается либо в подпрограммах, обрамленных примитивами 2.1, 2.2, 2.3, либо описывается в терминах языка ОККАМ с дополнительным синтаксическим указателем для компилятора или интерпретатора, требующем трансляции в машинный язык однопроцессорной ЭВМ.
Система параллельного программирования Оккам имеет все отладочные и оценочные средства: экранный редактор, синтаксический анализатор, средства структурного редактирования программ, программы для оценки получаемого ускорения по сравнению с однопроцессорной ЭВМ и требуемой памяти каждого из транспьютеров. Причем программы на языке Оккам предварительно транслируются и отлаживаются на однопроцессорной ЭВМ в режиме разделения времени, а затем дополняются требуемыми примитивами и синтаксическими указателями, с помощью которых описываются способы их параллельной загрузки в транспьютерную сеть и размещения локальных именованных процессов в памятях разных транспьютеров.
4.2.3.1. Примитивы и конструкции языка Оккам
Конструкции:
1. Последовательная конструкция SEQ:
SEQ[базаFORколичество]
P1
P2
.
.
.
→ со сдвигом на один символ и пробел.
Процессы P1,P2,….выполняются последовательно.
2.Параллельная конструкция PAR:
PAR[базаFORколичество]
P1
P2
.
.
.
→со сдвигом на один символ и пробел.
Процессы P1,P2,.…выполняются параллельно. Они начинаются синхронно, а завершаются по принципу барьерной синхронизации с применением в нужных местахFIFO-буферов. КонструкцияPARможет закончиться только тогда, когда завершатся все ее подчиненные параллельные процессы. В транспьютере при выполнениеPARна одном процессоре с разделением времени ведется учет числа незавершившихся ее подчиненных подпроцессов. Если же подчиненные процессыP1,P2,…выполняются в разных транспьютерах, то синхронизация их завершения выполняется программно с введениемFIFO-буферов.
Конструкция альтернативного выбора ALT
ALT [база FORколичество]
P1
P2
.
.
.
Выполняется первым любой из процессов P1,P2,…, готовый по уже поступившим значениям из входного канала связи. Если таких готовых процессов несколько, они выполняются последовательно, как вSEQ. Завершается после выполнения готовых к этому моменту процессов.
4. Условный конструктор WHILE:
WHILE<условие>
процесс
Процесс повторяется до тех пор, пока результат проверки логического условия не приобретет значения ложности FALSE.
5. Условный конструктор JF:
JF<условие>
Процесс
Процесс, кроме обычного ожидания ввода по входному каналу, блокируется до тех пор, пока условие не приобретет значения истинности TRUE.
Конструкторы можно размножать и повторять сколько угодно раз. Размножение применяется с использованием конструктора PAR, а путем повторения поWHILEможно имитировать условные циклы.
Примитивы:
1.Обьявление переменной (переменных):
VARимя 1, имя 2,…:
2.Объявление массива переменных:
VARимя [размер]:
3. Объявление каналов связи:
CHANимя 1, имя 2, .. :
4.Обьявление массива каналов связи:
CHANимя [размер]:
5. Объявление процесса:
PROCимя (параметры) =
В качестве параметров объявляютсяимена используемых процессом каналов.
6.Присваивание, изменяющее значение переменной:
a:=b+c
7. Ввод- получение из поименованного канала определенного значения и присваивание этого значения указанной переменной:
Chan1?a
8. Вывод- передача в поименованный канал значения переменной, указанной в примитиве:
Chan2!b+c
9. :-метка завершения примитивов объявления и текста программы (метка завершения Оккам процесса).
Часто применяемые подпрограммы:
Транзитная сквозная передача – ввод значения из одного канала и сразу же его вывод в другой канал без промежуточного хранения в ЛОП транспьютера:
Chan1 ?X
Chan2 !X
2. Транзитная передача значения с промежуточным его хранением в ЛОП транспьютера по адресу объявленного переменной:
VAR X:
SEQ
Chan 1 ? X
Chan 2 ! X
3.Параллельный ввод из двух входных каналов с присваиванием полученных значений объявленным переменным (с записью их в ЛОП по адресам этих переменных):
VAR X, Y:
PAR
Chan 1 ? X
Chan2 !Y
4.Реализация повторений с применением конструкции ALT, так называемое групповое транзитивное взаимодействие;
ALT i = [0 FOR 100]
Inp [i] ? X
Oup!X:
Этот процесс читает значение из первого любого по номеру передающего канала, имеющего на входе значение, поступившее от одноименного выходного канала другого процесса, в массиве входных каналов inp[i], присваивает его переменной Х и передает его в выходной каналoupи так далее, пока не обслужит все входные каналы с номерами от 0 до 100.
В динамике исполнения программа завершается после обслуживания всех передающих в данный момент каналов, имеющих на входе значения от выходных каналов других процессов.
4.2.3.2.Примеры программирования транспьютерных сетей на языке Оккам.
С помощью языка Оккам очень компактно описываются регулярные параллельные процедуры обработки регулярных массивов. Например, двумерный волновой алгоритм умножения двух квадратных матриц порядка nна транспьютерной сети размеромnnтранспьютеров может быть описан двумя короткими текстами. В этом алгоритме одна матрица поступает в квадратный матричный массив транспьютеров (плоскую решетку) слева по столбцам, а другая сверху - по строкам. По мере продвижения векторов данных вправо и вниз их компоненты попарно встречаются в транспьютерах, перемножаются и суммируются с накопленными частичными суммами в каждом транспьютере. После того, как все элементы исходных матриц последовательно волна за волной заnшагов будут загружены в транспьютерную сеть (решетку) и пройдут ее, в каждом транспьютере накопится сумма произведений пар элементов исходных матриц, равная искомому элементу результирующей матрицы. На каждом волновом фронте каждый транспьютер выполняет одинаковый локальный процесс- чтение данных из двух входных каналов связи: левого и верхнего, перемножение и накапливающее сложение и затем передачу использованной пары данных в другие выходные каналы: право и вниз в другие транспьютеры. Конечно, при этом необходимо с помощью буферов выполнить пространственно- временную синхронизацию пар входных операндов, т.е. обеспечить их синхронное поступление в нужный момент в нужный транспьютер.
Программа составляется как иерархическая двухуровневая. На нижнем уровне в каждом транспьютере выполняется одинаковая локальная программа :
PROC mult (CHAN up, down, left, right) =
С
.1
VAR ass, a, b:
Подчиненный
процесс А повторяется последовательно
n
раз на фронте каждой волны, начиная с
нулевой начальной установки и только
при i=n
срабатывает признак завершения (:).

→ SEQ
ass: =0

SEQ i = [0 FOR
n]
SEQ

PAR
up ? a
left ? b
А ass:=ass + a*b
PAR
down! а
right!b:
Здесь первый сдвиг С.1 синтаксически указывает компилятору, что данный процесс-это внутренняя программа транспьютера, и ее необходимо транслировать с переводом параллельных конструкций PARв последовательные вычисления в режиме разделения времени процессора транспьютера.
На втором высшем уровне программы транспьютерной сети выполняется глобальная организующая программа (структурная программа на языке Оккам), которая должна установить связи между локальными процессами и вызывать локальный процесс PROCmult…nnраз на каждой изnволн обработки:
С.1=0
CHAN vertical [n*(n-1)]:
вне CHAN horizontal [n*(n-1)]:
транспьютеров
PAR i = [0 FOR n]
PAR j= [0 For n]
mult (vertical [(n*i) +j],
vertical [(n*i) +j+1],
horizontal [(n*i)+j],
horizontal[(n*(i+1)) +j]):
По начальному синтаксическому признаку С.1=0 компилятор внесет в объектные коды локальных программ транспьютеров соответствующие операторы организации передачи данных вниз из строки в строку, и вправо из столбца в столбец решетки транспьютеров.
Для пространственно- временной синхронизации входных операндов локальных процессов необходимо вводить в вертикальные входные каналы транспьютеров, расположенных выше главной диагонали решетки, и в горизонтальные входные каналы транспьютеров, расположенных ниже главной ее диагонали, дополнительные FIFO- буферы (линии задержки), емкости которых линейно возрастают от 0 до (n-1) слов вправо и вниз от главной диагонали. Так как в последовательных портах и линках транспьютеров отсутствует аппаратные (регистровые) буферы, требуемую буферизацию можно ввести программно в локальные программы каждого из транспьютеров, как дополнительные локальные процессы на входах каналовupи каналовleftвсех транспьютеров выше и левее главной диагонали.
Принцип составления программы FIFO-буфера, имитирующей линию задержки, состоит в следующем.FIFO- буфер можно рассматривать как цепочку последовательно соединенных ячеек ОЗУ:

Здесь Х- это переменная, продвигающаяся по линии задержки с постоянным конвейерным тактом; C[i]- обозначение условного канала связи междуi- й и (i+1)- й ячейками ОЗУ, реализуемого путем передачи слова данных (значения переменной Х) из одной ячейки ОЗУ в другую через регистр процессора. Если подпрограмма буфера поименована как «PROCbuffer=» без объявления имен каналов, то компилятор интерпретирует имена каналов в ней как идентификаторы адресов ячеек ОЗУ. Кроме этого для того, чтобы не тратить время на продвижение по ячейкам ОЗУ нулевых значений при Х:=0, в программу буфера вводится конструкция:
WHILETRUE,
|процесс,
которая повторяет подчиненный процесс до тех пор, пока условие не станет FALSE, а по имени процедурыbufferпосле считывания из ячейки ОЗУ значения Х≠0 ее содержимое обязательно обнуляется.
Программа FIFO- буфера языка ОККАМ:
С.1≠0 PROC buffer=
в
нутри
→
CHAN c [n+1]:
т
ранспьютера
PAR i = [0 FOR n]
WHILE TRUE
VAR X:
SEQ
C [i]? X
C[i+1]!X:
Конструкция PARисполняется последовательно в режиме разделения времени процессора.
Так как после WHILEобъявлена только одна переменная Х, то по умолчанию Х≠0 интерпретируется какTRUE, а Х=0 - какFALSE, и поэтому при Х=0 передача из ячейкиC[i] в ячейкуC[i+1] ОЗУ не выполняется, а впереди освобождаемые ячейки автоматически обнуляются по признаку «buffer».
4.2.3.3. Встраивание программного FIFO-буфера при транзитной передаче
Если при параллельном программировании транспьютерных сетей потребуется промежуточная буферизация передаваемых сообщений, то программный буфер можно встроить между двумя внешними каналами ввода- вывода транзитного транспьютера. Тогда имена внешних каналов указываются в параметрах объявления процесса:
PROC buffer (CHAN C. in, C. out) =
CHANC[n-1]: объявление дополнительных внутренних каналов


WHILE TRUE
PAR
VAR X:
SEQ
C.IN?X ввод
в буфер
C. [0]! X
PAR i= [0 FOR n-2]
VAR X: SEQ C[i]?X
C(i+1)!X
VARX:
SEQC[n-2]?Xвывод из буфера
C.out!X:
Программа дополнена двумя процессами ввода из внешнего канала С.inи вывода во внешний каналC.out.
Принудительная синхронизация асинхронных вычислительных процессов при параллельном программировании на языке Оккам.
До сих пор мы рассматривали только синхронные параллельные процессы, когда требуемую пространственно–временную синхронизацию их входных операндов можно обеспечить с помощью дополнительных ОККАМ-FIFO-буферов. Однако на языке ОККАМ можно программировать также и асинхронные параллельные процессы. Тогда для синхронизации процессов необходимо блокирование (приостановка) одного процесса по инициативе другого процесса. Наиболее простой способ такой блокировки – это прерывание транзитной сквозной передачи данных из одного канала связи в другой, если эти каналы связывают два подпроцесса основного блокируемому процесса. Это можно выполнить по специальному сигналу останова, получаемого с выхода третьего канала транспьютера.
Напишем текст программы на языке ОККАМ, по которому данные копируются из одного канала С1 в другой С2 в стыке двух подпроцессов до тех пор, пока поступит управляющий сигнал останова (ANY) из третьего канала под именемStop:
VAR running:
SEQ
Running: = TRUE
WHILE running
VAR x:
ALT

Stop? ANY I
Running: = FALSE
C1? x
C2! x: II
По TRUEи конструкцииALTпоследовательно читаются входные каналыstop? иC1?. Если по каналуStop? в данный момент не поступало сообщений, то поALTчитается каналC1? и его значение копируется в выходной каналC2!. Так будет происходить до тех пор, пока не поступит сообщениеANYпо каналуstop. Тогда будет инициализировано присваивание по принципу последовательного исполнения после выполнения предыдущего примитива и переменнаяrunningпримет значениеFALSE. Далее поALTбудет выполнено последние копирование значения из каналаC1 в каналC2, процесс будет завершен и передача данных прервется. Тем самым основной процесс с такой промежуточной вставкой будет заблокирован. Для его разблокирования достаточно организовать повторное присваиваниеrunning:=TRUEпо инициативе любого другого процесса.
Во время такого блокирования предыдущие процессы и подпрограммы не будут считаться завершенными, т.к. значения из их выходных каналов не будут приняты, и поэтому они будут периодически инициализировать передачу своих выходных значений до тех пор, пока не получат подтверждение о приеме значения процессом-приемником, что произойдет только после разблокирования последнего. Следует учесть, что каждый передаваемый байт по линку между двумя транспьютерами имеет заглавную стартовую посылку 11…, а по обратной линии дуплексного линка сразу же приходит подтверждающая квитанция «01», если прием не заблокирован.
Достоинства языка Оккам:
С помощью конструкторов при параллельном программировании осуществляется наглядная иерархическая параллельная и последовательная декомпозиция сложных программ с минимизацией участия МОС ведущей ЭВМ в управлении взаимодействием декомпозированных процессов по сравнению с другими системами программирования мультикомпьютеров.
Язык очень прост и краток, но позволяет создавать сложные иерархические управляющие структуры.
Он позволяет обойтись без семафоров, очередей процессов, планировщиков, диспетчеров и обработки прерываний.
Его конструкции пригодны и для составления локальных программ процессов, и для описания главной глобальной программы параллельного вычислительного процесса в целом.
Компилятор языка ОККАМ может реализовать режим разделения времени процессора, что позволяет все программы на этом языке предварительно оттранслировать и отладить на однопроцессорной ЭВМ в многозадачном режиме с разделением времени.
Формальные структуры языка пригодны как для параллельного программирования, так и для формального описания параллельных структур многопроцессорных систем.
Теоретические основы распараллеливающего компилятора
По назначению распараллеливающие компиляторы подразделяются на два типа:
- командные компиляторы для VLIWиEPIGмикропроцессоров;
-фрагментные компиляторы для многопроцессорных мультипроцессоров и мультикомпьютеров.
Первые автоматизируют мелкозернистое распараллеливание в статике на уровне команд. Они основаны на рассмотренных выше методах переименования переменных, упреждающего исполнения команд по предположению (агрессивное исполнение на спекулятивных недостоверных операндах), замены команд условных переходов командами условного исполнения и предикации. Кроме этого используются методы расщепления и разворачивания циклов, трассировочного планирования и уплотнения трасс, переноса команд вперед через условные переходы, программной конвейеризации итераций циклов, редукции высоты дерева вычислений сложных арифметических выражений.
Завершается компиляция преобразованием исходной последовательной программы в ярусно- параллельною форму, где на ярусах помещаются подмножества параллельных команд, независимых между собой и неконфликтующих друг с другом. Из этих команд в пределах каждого яруса компонуются сверхдлинные командные слова, длиной до восьми RISCкоманд. Выполняется также совмещение в одномVLIWкомандразных ярусов на основе анализа зависимостей между командами разных ярусов и возможности их параллельного исполнения. Программы этих компиляторов очень сложны и содержат элементы искусственного интеллекта.
В тоже время в суперскалярных микропроцессорах распараллеливание на уровне команд выполняется автоматически в динамике исполнения исходных последовательных программ с помощью специальных аппаратных средств. Для них не требуются специальные компиляторы распараллеливания на уровне команд в статике.
Учитывая это, а также то, что распараллеливание на уровне команд не позволяет повысить производительность более, чем в 10 раз, а реально достигнутое ускорение составляет около 2-8 раз, уделим внимание второму типу фрагментных компиляторов, автоматизирующих среднезернистое и крупнозернистое распараллеливание на уровне программ и заданий. Они разбивают в статике исходные последовательные программы на группы (блоки, пакеты) команд, подпрограммы (фрагменты, треды), ветви, потоки или нити в терминах ОС UNIXиWindows. Исходные последовательные программы преобразуются в ярусно- параллельные формы, но на ярусах помещаются не отдельные команды, а подпрограммы фрагментов (тредов), исполняемых параллельно в нескольких процессорах. Если в качестве обрабатывающих процессоров применить суперскалярные микропроцессоры, то более мелкое распараллеливание на уровне команд будет выполнено автоматически вдинамикеаппаратными средствами процессоров. Такое сочетание распараллеливания встатикена уровне программ и заданий, в том числе и планирования встатике параллельной обработки нераспараллеливаемых независимых исходных программ, с автоматическим распараллеливанием на уровне команд в динамике позволяет ускорить обработку в многопрограммных (многозадачных) режимах на менее, чем 100 раз.
В фрагментных компиляторах применяются следующие методы распараллеливания:
- распараллеливание линейных участков с учетом независимости между блоками команд, искусственно введенными в последовательные ветви при программировании однопроцессорной ЭВМ;
-распараллеливание итераций сложных вложенных циклов;
-разбиение исходных сложных последовательных программ, после их предварительного распараллеливания, на множество параллельно-последовательных задач по критерию максимального ускорения их исполнения на многопроцессорной ВС при ограничениях на вычислительную сложность задач и число связей между ними;
-разбиение совокупностиисходных предварительно распараллеленных последовательных программ на смесь исполняемых задач и предварительное планирование их параллельно–последовательной обработки на многопроцессорной ВС по критерию максимального ускорения при ограничениях на вычислительную сложность задач и число связей между ними. В общем случае в совокупность обрабатываемых исходных последовательных программ могут входить и такие, распараллеливание которых либо невозможно, либо нецелесообразно по ограничению сверху на вычислительную сложность. Тогда некоторые из них разбиваются на цепь последовательно исполняемых задач ограниченной сложности. Образовавшаяся смесь задач путем планирования с учетом зависимости и независимости между ними трансформируется в ярусно-параллельный массив с максимальной шириной ярусов задач, не превышающей число наличных процессов. Такое предварительное планирование параллельно-последовательной обработки смеси задач создает лишь предпосылки для возможности ускорения обработки совокупности исходных последовательных программ в мультипрограммном режиме.
Реально достигаемое ускорение зависит от качества диспетчеризации задач в динамике их асинхронной параллельно-последовательной обработки на многопроцессорной ВС. Диспетчеризацию задач можно исключить и при этом достичь ускорения, прогнозируемого предварительным планированием, если организовать макропотоковую параллельно- последовательную обработку по степени готовности входных операндов задач. Для этого достаточно создать и модифицировать очередь готовых к обработке задач и из нее передавать по одной задаче на обработку в любой свободный или освободившийся процессор. По- видимому при макропотоковой обработке произвольнойсовокупности исходных последовательных программ, разбитой компилятором на смесь задач (тредов) ограниченной сложности, предварительное планирование не обязательно, так как оно не даст существенного ускорения и фактически будет выполняться автоматически по ходу обслуживания очереди готовых задач (тредов) свободными процессорами.
Существенное ускорение можно получить, если исполняемые задачи (треды) будут соответствовать параллельным фрагментам (подпрограммам), получаемым в результате распараллеливания сложных исходных последовательных программ.
Распараллеливание линейных участков с учетом независимости между их фрагментами.
Резерв по распараллеливанию линейных участков исходных последовательных программ обусловлен следующими факторами:
- при последовательном программировании однопроцессорных ЭВМ явный параллелизм фрагментов обычно не указывается и такие фрагменты объединяются в последовательные линейные участки; поэтому в сложных последовательных программах часто содержится скрытый (неявный) параллелизм групп команд (подпрограмм);
- с целью экономии оперативной памяти в наследуемых последовательных программах часто один и тот же идентификатор может обозначать разные переменные, так как одна и та же ячейка используется для хранения разных переменных путем замещения; поэтому фактически независимые операторы или подпрограммы формально считаются информационно связанными.
Компилятор прежде всего выявляет в статике скрытый параллелизм второго типа и устраняет ложные зависимости между командами путем замены переменных, переименования переменных, аналогично переименованию регистров, выполняемому суперскалярным процессором в динамике. Автоматическое выявление и устранение ложных (лишних) зависимостей между командами в статике выполняется построением булевых матриц переменных линейных участков и составлением матриц транзитивного замыкания, а затем путем анализа строк и столбцов этих матриц вводятся новые переменные и модифицируется объектный код исходных программ.
После устранения лишних зависимостей преобразованная исходная программа подвергается распараллеливанию с использованием информационной независимости между фрагментами ее линейных участков.
Определим понятие информационной независимости. Два оператора FiиFjпоследовательного линейного участка:
{Oi} =Fi{Ii},
{Oj} =Fj{Ij},
где Ii,Ij– идентификаторы входных переменных (операндов) операторовFiиFjсоответственно;
Oi,Oj–идентификаторы выходных переменных (результатов);
считаются информационно – независимыми, если множества идентификаторов их входных и выходных переменных подчиняются следующим соотношениям:
Ij∩Oi=Ø,Ii∩Oj=Ø,Oi∩Oj= Ø.
Первые два требования означают, что, если операторы независимы, входы одного оператора не могут быть выходами другого. Третье требование означает, что не используются одни и те же идентификаторы для выходных переменных в обоих операторах, т.е. не выполняется запись выходных переменных двух операторов в одни и те же ячейки памяти, например по принципу замещения.
Рассмотрим методику распараллеливающего
преобразования на простом примере
последовательной программы, содержащих
один условный переход и два линейных
участка, где
-
условное обозначениеFiоператора.

Исходная программа может быть описана пятью матрицами:
матрица смежности С;
матрица условных передач управления L;
матрица входов I операторов;
матрица выходов Oоператоров;
матрица последовательности выполнения алгоритма P.
Составим все названные матрицы для нашего примера.
Матрица смежности С размером 88, гдеi,j-номера операторов, а «1»-код наличия направленной дуги отjкi.

Матрица условных передач управления Lразмером 88, где код «1»- код наличия направленной дуги перехода по «нет» или по «да» отjki, а остальные элементы нулевые.

Матрица входов Iоператоров
размеромnm(85), где
-
номера операторов,
-
номера входных переменных и массивов;
код «1», еслиj-я переменная
(массив) является входной дляi-го
оператора.

Матрица выходов О операторов размером
nm,
где
-номера
выходных переменных (массивов); код «1»,
еслиj-я переменная (массив)
является выходной дляi-го
оператора.

Матрица последовательности выполнения алгоритма Pразмером 88, где код «1», еслиi-му оператору предшествует выполнениеj-го оператора.

Как следует из матриц IиOпоследовательное расположение операторов на линейных участках в исходной программе было выполнено программистом вынужденно, так как в ЭВМ был один процессор. Строгой последовательной передачи выходных результатов предыдущих операторов сразу же на вход следующего оператора нет. Это является резервом для распараллеливания.
Основная цель распараллеливающей компиляции – преобразование программы и ее матрицы смежности С → Cpтаким образом, чтобы выявить скрытый параллелизм и трансформировать линейные участки в ярусы параллельных операторов. Такое преобразование возможно, если имеется информационная независимость между операторами линейных участков. ПреобразованиеC→Cpвыполняется путем построения двух вспомогательных матриц:
- матрицы неполного параллелизма выполнения операций Pp;
- матрицы параллельной логики Lp.
