Written by: Posted on: 20.08.2014

Параллельное и распределенное программирование с использованием c камерон хьюз, трейси хьюз

У нас вы можете скачать книгу параллельное и распределенное программирование с использованием c камерон хьюз, трейси хьюз в fb2, txt, PDF, EPUB, doc, rtf, jar, djvu, lrf!

Задача А получает запросы от задачи В на выполнение операций снятия денег со счета. Задача А также получает запросы от задачи С положить деньги на депозит.

Предположим, на счете имеется долл. Что произойдет, если обе задачи В и С попытаются обновить один и тот же счет одновременно? Каким будет остаток на счете? Очевидно, остаток на счете в каждый момент времени не может иметь более одного значения.

Задача А применительно к счету должна выполнять одновременно только одну транзакцию, то есть мы сталкиваемся с проблемой координации задач.

Если запрос задачи В будет выполнен на какую-то долю секунды быстрее, чем запрос задачи С, то счет приобретет отрицательный баланс. Но если задача С получит первой право на обновление счета, то этого не произойдет.

Таким образом, остаток на счете зависит от того, какой задаче В или С первой удастся сделать запрос к задаче А. Более того, мы можем выполнять задачи В и С несколько раз с одними и теми же значениями, и при этом иногда запрос задачи В будет произведен на какую-то долю секунды быстрее, чем запрос задачи С, а иногда — наоборот. Очевидно, что необходимо организовать надлежащую координацию действий. Для координации задач, выполняемых параллельно, требуется обеспечить связь между ними и синхронизацию их работы.

При некорректной связи или синхронизации обычно возникает четыре типа проблем. Какая задача в нашей программе поддержки электронного банка первой получит доступ к остатку на счете, определяется результатом работы планировщика задач операционной системы, состоянием процессоров, временем ожидания и случайными причинами.

И какое значение в этом случае должен сообщать банк в качестве реального остатка на счете? Итак, несмотря на то, что мы хотели бы, чтобы наша программа позволяла одновременно обрабатывать множество операций по снятию денег со счета и вложению их на депозит, нам нужно координировать эти задачи в случае, если окажется, что операции снятия и вложения денег должны быть применены к одному и тому же счету.

Всякий раз когда задачи одновременно используют модифицируемый ресурс, к ресурсному доступу этих задач должны быть применены определенные правила и стратегии. Например, в нашей программе поддержки банковских операций со счетами мы могли бы всегда выполнять любые операции по вложению денег до выполнения каких бы то ни было операций по их снятию.

Мы могли бы установить правило, в соответствии с которым доступ к счету одновременно могла получать только одна транзакция. И если окажется, что к одному и тому же счету одновременно обращается сразу несколько транзакций, их необходимо задержать, организовать их выполнение в соответствии с некоторым правилом очередности, а затем предоставлять им доступ к счету по одной в порядке очереди.

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

И точно так же, если ожидаемое событие или условие, которое по нашему мнению должно произойти или наступить , но в действительности не происходит или не наступает , то приостановленные нами задачи будут вечно находиться в состоянии ожидания. Если мы приостановим одну или несколько задач до наступления события или условия , которое никогда не произойдет, возникнет ситуация, называемая бесконечной отсрочкой indefinite postponement. Возвращаясь к нашему примеру электронного банка, предположим, что, если мы установим правила, предписывающие всем задачам снятия денег со счета находиться в состоянии ожидания до тех пор, пока не будут выполнены все задачи вложения денег на счет, то задачи снятия денег рискуют стать бесконечно отсроченными.

Мы исходили из предположения о гарантированном существовании задач вложения денег на счет. Но если ни один из запросов на пополнение счетов не поступит, то что тогда заставит выполниться задачи снятия денег? И, наоборот, что, если будут без конца поступать запросы на пополнение одного и того же счета? Такая ситуация также может вызвать бесконечную отсрочку задач снятия денег. Бесконечная отсрочка возникает при отсутствии задач вложения денег на счет или их постоянном поступлении.

Необходимо также предусмотреть ситуацию, когда запросы на вложение денег поступают корректно, но нам не удается надлежащим образом организовать связь между событиями и задачами. По мере того как мы будем пытаться скоординировать доступ параллельных задач к некоторому общему ресурсу данных, следует предусмотреть все ситуации, в которых возможно создание бесконечной отсрочки.

Методы, позволяющие избежать бесконечных отсрочек, рассматриваются в главе 5. Для демонстрации взаимоблокировки предположим, что в нашей программе поддержки электронного банка три задачи работают не с одним, а с двумя счетами. Вспомним, что задача А получает запросы от задачи В на снятие денег со счета, а от задачи С — запросы на вложение денег на депозит.

Задачи А, В и С могут выполняться параллельно. Однако задачи В и С могут обновлять одновременно только один счет. Предположим также, что задача В имеет монопольный доступ к счету 1, а задача С — монопольный доступ к счету 2. При этом задаче В для выполнения соответствующей обработки также нужен доступ к счету 2 и задаче С — доступ к счету 1.

Задача В удерживает счет 1, ожидая, пока задача С не освободит счет 2. Аналогично задача С удерживает счет 2, ожидая, пока задача В не освободит счет 1. Тем самым задачи В и С рискуют попасть в тупиковую ситуацию , которую в данном случае можно назвать взаимоблокировкой deadlock. Ситуация взаимоблокировки между задачами В и С схематично показана на рис. Форма взаимоблокировки в данном случае объясняется наличием параллельно выполняемых задач, имеющих доступ к совместно используемым данным, которые им разрешено обновлять.

Здесь возможна ситуация, когда каждая из задач будет ожидать до тех пор, пока другая не освободит доступ к общим данным общими данными здесь являются счет 1 и счет 2. Обе задачи имеют доступ к обоим счетам. Поскольку задача В не может освободить счет 1, пока не получит К туп к счету 2, а задача С не может освободить счет 2, пока не получит доступ к счету 1, программа обслуживания счетов электронного банка будет оставаться заблокированной.

Обратите внимание на то, что задачи В и С могут ввести в состояние бесконечной отсрочки и другие задачи если таковые имеются в системе. При координации параллельно выполняемых задач необходимо помнить, что взаимоблокировка и бесконечная отсрочка — это самые опасные преграды, которые нужно предусмотреть и избежать.

Многие распространенные параллельные среды например, кластеры зачастую состоят из гетерогенных компьютерных сетей. Гетерогенные компьютерные сети— это системы, которые состоят из компьютеров различных типов, работающих в общем случае под управлением различных операционных систем и использующих различные сетевые протоколы.

Их процессоры могут иметь различную архитектуру, обрабатывать слова различной длины и использовать различные машинные языки. Помимо разных операционных систем, компьютеры могут различаться используемыми стратегиями планирования и системами приоритетов. Хуже того, все системы могут различаться параметрами передачи данных. Это делает обработку ошибок и исключительных ситуаций исключений особенно трудной. Неоднородность системы может усугубляться и другими различиями.

Например, может возникнуть необходимость организации совместного использования данных программами, написанными на различных языках или разработанных с использованием различных моделей ПО. Это вносит проблемы межъязыковой связи. И даже если распределенная или параллельная среда не является гетерогенной, остается проблема взаимодействия между несколькими процессами или потоками. Поскольку каждый процесс имеет собственное адресное пространство, то для совместного использования переменных, параметров и значений, возвращаемых функциями, необходимо применять технологию межпроцессного взаимодействия interprocess communication — IPC , или МПВ-технологию.

И хотя реализация МПВ-методов необязательно является самой трудной частью разработки системы ПО, тем не менее они образуют дополнительный уровень проектирования, тестирования и отладки в создании системы. POSIX-спецификация поддерживает пять базовых механизмов, используемых для реализации взаимодействия между процессами:. Каждый из этих механизмов имеет достоинства, недостатки, ловушки и тупики, которые проектировщики и разработчики ПО должны обязательно учитывать, если хотят создать надежную и эффективную связь между несколькими процессами.

Организовать взаимодействие между несколькими потоками которые иногда называются облегченными процессами обычно проще, чем между процессами, так как потоки используют общее адресное пространство. Это означает, что каждый поток в программе может легко передавать параметры, принимать значения, возвращаемые функциями, и получать доступ к глобальным данным.

Необходимо отметить, что перечисленные выше проблемы характерны как для распределенного, так и для параллельного программирования. Несмотря на то что системы с исключительно параллельной обработкой отличаются от систем с исключительно распределенной обработкой, мы намеренно не проводили границу между проблемами координации в распределенных и параллельных системах.

Частично мы можем объяснить это некоторым перекрытием существующих проблем, и частично тем, что некоторые решения проблем в одной области часто применимы к проблемам в другой. Современное положение в параллельном способе обработке данных определяют кластеры и сетки. Причудливые кластерные конфигурации составляют из готовых продуктов. Такие архитектуры включают множество компьютеров со многими процессорами, а однопроцессорные системы уже уходят в прошлое.

В будущем предполагается, что чисто распределенные системы будут встраиваться в виде компьютеров с несколькими процессорами. Это означает, что на практике проектировщик или разработчик ПО будет теперь все чаще сталкиваться с проблемами распределения и параллелизма. Вот потому-то мы и рассматриваем все эти проблемы в одном пространстве. В этом случае подходит применение библиотеки PVM.

И точно так же существуют конфигурации, в которых распределение может быть достигнуто лишь на одном компьютере за счет разбиения логики ПО на несколько процессов или потоков. Комбинации параллельного и распределенного программирования, представленные в табл.

Комбинации параллельного и распределенного программирования с различными конфигурациями аппаратного обеспечения. Независимо от используемой конфигурации аппаратных средств, существует два базовых механизма, обеспечивающих взаимодействие нескольких задач: Эффективное использование обоих механизмов подробно рассматривается ниже в этой книге. При совместной работе множества процессоров над решением некоторой задачи возможен отказ одного или нескольких процессоров.

Каким в этом случае должно быть поведение ПО? Программа должна остановиться или возможно перераспределение работы? Что случится, если при использовании мультикомпьютерной системы канал связи между несколькими компьютерами временно выйдет из строя?

Что произойдет, если поток данных будет настолько медленным, что процессы на каждом конце связи превысят выделенный им лимит времени? Как ПО должно реагировать на подобные ситуации? Если, предположим, во время работы системы, состоящей из 50 компьютеров, совместно работающих над решением некоторой проблемы, произойдет отказ двух компьютеров, то должны ли остальные 48 взять на себя их функции?

Если в нашей программе электронного банка при одновременном выполнении задач по снятию и вложению денег на счет две задачи попадут в ситуацию взаимоблокировки, то нужно ли прекратить работу серверной задачи? И что тогда делать с заблокированными задачами? Что делать с частичными отказами или прерывистой работой?

Подобные вопросы обычно не возникают при работе последовательных программ в одно-компьютерных средах. Иногда отказ системы является следствием административной политики или стратегии безопасности. Например, предположим, что система содержит подпрограмм, и некоторым из них требуется доступ к файлу для записи в него информации, но они по какой-то причине не могут его получить.

В результате возможны взаимоблокировка, бесконечная отсрочка или частичный отказ. А как быть, если некоторые подпрограммы блокируются из-за отсутствия у них прав доступа к нужным ресурсам? Насколько можно доверять обработанной информации, если в системе произошли сбои в оборудовании, отказ каналов связи или их работа была прерывистой? Тем не менее эти ситуации очень даже характерны можно сказать, являются нормой для распределенных или параллельных сред. В этой книге мы рассмотрим ряд архитектурных решений и технологий программирования, которые позволят программному обеспечению системы справляться с подобными ситуациями.

Сложность синхронизации или уровень связи между процессорами может потребовать таких затрат вычислительных ресурсов, что они отрицательно скажутся на производительности задач, совместно выполняющих общую работу. Как узнать, на сколько процессов, задач или потоков следует разделить программу?

И, вообще, существует ли оптимальное количество процессоров для любой заданной параллельной программы? Нетрудно предположить, что рассматриваемые числа зависят от конкретной программы. В некоторых областях имитационного моделирования максимальное число процессоров может достигать нескольких тысяч, в то время как в коммерческих приложениях можно ограничиться несколькими сотнями.

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

Предел числа программных процессов может быть достигнут задолго до того, как будет достигнуто оптимальное количество процессоров или компьютеров. И точно так же можно наблюдать снижение эффективности оборудования еще до достижения оптимального количества параллельно выполняемых задач. Существует множество архитектурных решений, которые поддерживают параллелизм. Архитектурное решение можно считать корректным, если оно соответствует декомпозиции работ work breakdown structure — WBR программного обеспечения ДР ПО.

Параллельные и распределенные архитектуры могут быть самыми разнообразными. В то время как некоторые распределенные архитектуры прекрасно работают в Web-среде, они практически обречены на неудачу в среде с реальным масштабом времени. Например, распределенные архитектуры, которые рассчитаны на длинные временные задержки, вполне приемлемы для Web-среды и совершенно неприемлемы для многих сред реального времени.

Достаточно сравнить распределенную обработку данных в Web-ориентированной системе функционирования электронной почты с распределенной обработкой данных в банкоматах, или автоматических кассовых машинах automated teller machine— ATM. Задержка время ожидания , которая присутствует во многих почтовых Web-системах, была бы попросту губительной для таких систем реального времени, как банкоматы.

Одни распределенные архитектуры имеются в виду некоторые асинхронные модели справляются с временными задержками лучше, чем другие. Кроме того, необходимо самым серьезным образом подходить к выбору соответствующих архитектур параллельной обработки данных.

Например, методы векторной обработки данных наилучшим образом подходят для решения определенных математических задач и проблем имитационного моделирования, но они совершенно неэффективны в применении к мультиагентным алгоритмам планирования.

Распространенные архитектуры ПО, которые поддерживают параллельное и распределенное программирование, показаны в табл. Четыре базовые модели, перечисленные в табл. Разработчикам ПО необходимо подробно ознакомиться с каждой из этих моделей и их приложением к параллельному и распределенному программированию. Мы считаем своим долгом предоставить читателю введение в эти модели и дать библиографические сведения по материалам, которые позволят найти о них более детальную информацию. В каждой работе или при решении проблемы лучше всего искать естественный или присущий им параллелизм, а выбранный тип архитектуры Должен максимально соответствовать этому естественному параллелизму.

При тестировании последовательной программы разработчик может отследить ее логику в пошаговом режиме. Если он будет начинать тестирование с одних и тех же данных при условии, что система каждый раз будет пребывать в одном и том же состоянии, то результаты выполнения программы или ее логические цепочки будут вполне предсказуемыми.

Программист может отыскать ошибки в программе, используя соответствующие входные данные и исходное состояние программы, путем проверки ее логики в пошаговом режиме. Тестирование и отладка в последовательной модели зависят от степени предсказуемости начального и текущего состояний программы, определяемых заданными входными данными. С параллельным и распределенным программированием все обстоит иначе. Здесь трудно воспроизвести точный контекст параллельных или распределенных задач из-за разных стратегий планирования, применяемых в операционной системе, динамически меняющейся рабочей нагрузки, квантов процессорного времени, приоритетов процессов и потоков, временных задержек при их взаимодействии и собственно выполнении, а также различных случайных изменений ситуаций, характерных для параллельных или распределенных контекстов.

Чтобы воспроизвести точное состояние в котором находилась среда при тестировании и отладке, необходимо воссоздать каждую задачу, выполнением которой была занята операционная система. При этом должен быть известен режим планирования процессорного времени и точно воспроизведены состояние виртуальной памяти и переключение контекстов. Кроме того, следует воссоздать условия возникновения прерываний и формирования сигналов, а в некоторых случаях — даже рабочую нагрузку сети.

При этом нужно понимать, что и сами средства тестирования и отладки оказывают немалое влияние на состояние среды. Это означает, что создание одинаковой последовательности событий для тестирования и отладки зачастую невозможно. Необходимость воссоздания всех перечисленных выше условий обусловлено тем, что они позволяют определить, какие процессы или потоки следует выполнять и на каких именно процессорах.

И хотя некоторые из этих проблем встречаются и в последовательном программировании, они не в силах зачеркнуть допущения, сделанные при построении последовательной модели. Тот уровень предсказуемости, который имеет место в последовательной модели, недоступен для параллельного программирования. Это заставляет разработчика овладевать новыми тактическими приемами для тестирования и отладки параллельных и распределенных программ, а также требует от него поиска новых способов доказательства корректности его программ.

При создании документации на проектирование параллельного или распределенного ПО необходимо описать декомпозицию работ и их синхронизацию, а также взаимодействие между задачами, объектами, процессами и потоками. При этом проектировщики должны тесно контактировать с разработчиками, а разработчики — с теми, кто будет поддерживать систему и заниматься ее администрированием.

В идеале это взаимодействие должно осуществляться по действующим стандартам. Однако найти единый язык, понятный всем сторонам и позволяющий четко представить мультипарадигматическую природу всех этих систем, — трудно достижимая цель.

Семь диаграмм, перечисленных в табл. В частности, UML-диаграмм деятельности, развертывания и состояний весьма полезны для описания взаимодействующего поведения параллельной и распределенной подсистем обработки данных.

Поскольку UML — это фактический стандарт, используемый при создании взаимодействующих объектно-ориентированных и агентно-ориентированных проектов, при изложении материала в этой книге мы опираемся именно на него.

Описание обозначений и символов, используемых в перечисленных выше диаграммах, содержится в приложении А. UML-диаграммы, используемые при создании многопоточных, параллельных или распределенных программ. Диаграмма видов деятельности - разновидность диаграммы состояний, в которой большинство состояний или все представляют виды деятельности, а большинство переходов или все активизируются при выполнении некоторого действия в исходных состояниях. Диаграмма взаимодействия - Тип диаграммы, которая отображает взаимодействие между объектами.

Взаимодействия описываются в виде сообщений, которыми они обмениваются. К диаграммам взаимодействия относятся диаграммы сотрудничества, диаграммы последовательностей и диаграммы видов деятельности.

Диаграмма параллельных состояний - Диаграмма, которая показывает последовательность преобразований объекта в процессе его реакции на события. При использовании диаграммы параллельных состояний эти преобразования могут происходить в течение одного и того же интервала времени.

Диаграмма последовательностей - Диаграмма взаимодействия, в которой отображается организация структуры объектов, принимающих или отправляющих сообщения с акцентом на упорядочении сообщений по времени. Диаграмма сотрудничества - Диаграмма взаимодействия, в которой отображается организация структуры объектов, принимающих или отправляющих сообщения с акцентом на структурной организации.

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

При создании параллельного и распределенного ПО разработчиков ожидает множество проблем. Поэтому при проектировании ПО им необходимо искать новые архитектурные подходы и технологии. Многие фундаментальные допущения, которых придерживались разработчики при построении последовательных моделей программирования, совершенно неприемлемы в области создания параллельного и распределенного ПО. В программах, включающих элементы параллелизма, программисты чаще всего сталкиваются со следующими четырьмя проблемами координации: Наличие параллелизма и распределения оказывает огромное влияние на все аспекты жизненного цикла разработки ПО: Коль выполнение параллельных процессов возможно на более низком нейронном уровне, то на символическом уровне мышление человека с принципиальной точки зрения можно рассматривать как последовательную машину, которая использует временно создаваемые последовательности процессов, выполнение которых длится сотни миллисекунд.

Процесс process — это некоторая часть единица работы, создаваемая операционной системой. Важно отметить, что процессы и программы — необязательно эквивалентные понятия. Программа может состоять из нескольких процессов. В некоторых ситуациях процесс может быть не связан с конкретной программой. Процессы - это артефакты операционной системы, а программы — это артефакты разработчика.

Чтобы некоторую часть работы можно было назвать процессом, она должна иметь адресное пространство, назначаемое операционной системой, и идентификатор, или идентификационный номер id процесса. Процесс должен обладать определенным статусом и иметь свой элемент в таблице процессов. В соответствии со стандартом POSIX он должен содержать один или несколько потоков управления, выполняющихся в рамках его Процесс состоит из множества выполняющихся инструкций, размещенных в адресном пространстве этого процесса.

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

Процесс выполняет свои инструкции в течение некоторого периода времени. Затем он выгружается, освобождая процессор для другого процесса.

Планировщик операционной системы переключается с кода одного процесса на код другого, предоставляя каждому процессу шанс выполнить свои инструкции. Различают пользовательские процессы и системные.

Процессы, которые выполняют системный код, называются системными и применяются к системе в целом. Они занимаются выполнением таких служебных задач, как распределение памяти, обмен страницами между внутренним и вспомогательным запоминающими устройствами, контроль устройств и т.

Пользовательские процессы выполняют собственный код и иногда обращаются к системным функциям. Выполняя собственный код, пользовательский процесс пребывает в пользовательском режиме user mode. В пользовательском режиме процесс не может выполнять определенные привилегированные машинные команды. При вызове системных функций например read , write или open пользовательский процесс выполняет инструкции операционной системы. Для выполнения системного вызова процессор обращается к ядру операционной системы.

В это время о пользовательском процессе говорят, что он пребывает в привилегированном режиме, или режиме ядра kernel mode , и не может быть выгружен никаким другим пользовательским процессом. Процессы имеют характеристики, используемые для идентификации и определения их поведения.

Ядро поддерживает необходимые структуры данных и предоставляет системные функции, которые дают возможность пользователю получить доступ к этой информации. Данные, хранимые в БУП-блоках, описывают процесс с точки зрения потребностей операционной системы. С помощью этой информации операционная система может управлять каждым процессом.

Когда операционная система переключается с одного процесса на другой, она сохраняет текущее состояние выполняющегося процесса и его контекст в области сохранения БУП-блока, чт обы надлежащим образом возобновить выполнение этого процесса в следующий раз, когда ему снова будет выделен центральный процессор ЦП. БУП-блок считывается и обновляется различными модулями операционной системы. Блок БУП содержит следующую информацию:. Кроме того, этот блок включает информацию, связанную с планированием, привилегиями процессов, флагами, сообщениями и сигналами, которыми обмениваются процессы имеется в виду межпроцессное взаимодействие— mterprocess communication, или IPC.

С помощью информации, связанной с управлением процессами, операционная система может координировать параллельно выполняемые процессы. Стековые указатели и содержимое регистров пользователя, управления и состояния содержат информацию, связанную с состоянием процессора. При выполнении процесса соответствующая информация размещается в регистрах ЦП. При переключении операционной системы с одного процесса на другой вся информация из этих регистров сохраняется. Есть еще один вид информации, который связан с идентификацией процесса.

Эти идентификационные номера которые представлены положительными целочисленными значениями уникальны для каждого процесса. Если же компьютер содержит только один процессор, то иллюзия параллелизма обеспечивается за счет процесса переключения контекстов.

Все библиотеки предлагают модели параллелизма, которые имеют незначительные различия. Предпочтительно используется для модели SPMD. Содержит эффективные средства поддержки агентно-ориентированного и мультиагентного программирования.

Наиболее распространенными средами для параллельного и распределенного программирования являются кластеры, SMP- и МРР-компьютеры. Кластеры — это коллекции, состоящие из нескольких компьютеров, объединенных сетью для создания единой логической системы. С точки зрения приложения такая группа компьютеров выглядит как один виртуальный компьютер. Под MPP-конфигурацией Massively Parallel Processors — процессоры с массовым параллелизмом понимается один компьютер, содержащий сотни процессоров, а под SMP-конфигурацией symmetric multiprocessor — симметричный мультипроцессор — единая система, в которой тесно связанные процессоры совместно используют общую память и информационный канал.

SMP-процессоры разделяют общие ресурсы и являются объектами управления одной операционной системы. Поскольку эта книга представляет собой введение в параллельное и распределенное программирование, нас будут интересовать небольшие кластеры, состоящие из процессоров, и многопроцессорные компьютеры с двумя-четырьмя процессорами. И хотя многие рассматриваемые здесь методы можно использовать в MPP- или больших SMP-средах, мы в основном уделяем внимание системам среднего масштаба.

В этой книге представлен архитектурный подход к параллельному и распределенному программированию. При этом акцент ставится на определении естественного параллелизма в самой задаче и ее решении, который закрепляется в программной модели решения. Мы предлагаем использовать объектно-ориентированные методы, которые бы позволили справиться со сложностью параллельного и распределенного программирования, и придерживаемся следующего принципа: Рекомендуемые нами библиотеки базируются на национальных и международных стандартах.

Каждая библиотека легко доступна и широко используется программистами во всем мире. Методы и идеи, представленные в этой книге, не зависят от конкретных изготовителей программных и аппаратных средств, общедоступны и опираются на открытые стандарты и открытые архитектуры.

Наряду с достоинствами, параллельное и распределенное программирование не лишено многих проблем, которые рассматриваются в следующей главе. В базовой последовательной модели программирования инструкции компьютерной программы выполняются поочередно. Разработчик программы разбивает основную задачу ПО на коллекцию подзадач. Все задачи выполняются по порядку, и каждая из них должна ожидать своей очереди.

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

В последовательной модели зачастую устанавливается последовательная зависимость задач. Это означает, что задаче А необходимы результаты выполнения задачи В, а задаче В нужны результаты выполнения задачи С, которой требуется что-то от задачи D и т. Если при выполнении задачи В по какой-то причине произойдет сбой, задачи С и D никогда не п риступят к работе. В таком последовательном мире разработчик привычно ориентирует ПО сначала на выполнение действия 1, затем — действия 2, за которым должно следовать действие 3 и т.

Подобная последовательная модель настолько закрепилась в процессе проектирования и разработки ПО, что многие программисты считают ее незыблемой и не допускают мысли о возможности иного положения вещей. Решение каждой проблемы, разработка каждого алгоритма и планирование каждой структуры данных — все это делалось с мыслью о последовательном доступе компьютера к каждой инструкции или ячейке данных.

В мире параллельного программирования все обстоит по-другому. Здесь сразу несколько инструкций могут выполняться в один и тот же момент времени. Одна инструкция разбивается на несколько мелких частей, которые будут выполняться одновременно. Программа разбивается на множество параллельных задач.

Программа может состоять из сотен или даже тысяч выполняющихся одновременно подпрограмм. В мире параллельного программирования последовательность и местоположение составляющих ПО не всегда предсказуемы. Несколько задач могут одновременно начать выполнение на любом процессоре без какой бы то ни было гарантии того, что задачи закреплены за определенными процессорами, или такая-то задача завершится первой, или все они завершатся в таком-то порядке.

Помимо параллельного выполнения задач, здесь возможно параллельное выполнение частей подзадач одной задачи. В некоторых конфигурациях не исключена возможность выполнения подзадач на различных процессорах или даже различных компьютерах. Модель программы, показанная на рис. Здесь отображены три уровня параллелизма и их распределение по нескольким процессорам. Сочетание этих трех уровней с базовыми параллельными конфигурациями процессоров показано на рис.

Обратите внимание на то, что несколько задач может выполняться на одном процессоре даже при наличии в компьютере нескольких процессоров. Такая ситуация создается системными стратегиями планирования. На длительность выполнения задач, подзадач и инструкций оказывают влияние и выбранные стратегии планирования, и приоритеты процессов, и приоритеты потоков, и быстродействие устройств ввода-вывода. Основное различие в моделях состоит в переходе от строго упорядоченной последовательности задач к лишь частично упорядоченной или вовсе неупорядоченной коллекции задач.

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

Предположим, у нас есть программа поддержки электронного банка, которая позволяет снимать деньги со счета и класть их на депозит. Допустим, что эта программа разделена на три задачи обозначим их А, В и С , которые могут выполняться параллельно.

Задача А получает запросы от задачи В на выполнение операций снятия денег со счета. Задача А также получает запросы от задачи С положить деньги на депозит. Предположим, на счете имеется долл. Что произойдет, если обе задачи В и С попытаются обновить один и тот же счет одновременно?

Каким будет остаток на счете? Очевидно, остаток на счете в каждый момент времени не может иметь более одного значения. Задача А применительно к счету должна выполнять одновременно только одну транзакцию, то есть мы сталкиваемся с проблемой координации задач. Если запрос задачи В будет выполнен на какую-то долю секунды быстрее, чем запрос задачи С, то счет приобретет отрицательный баланс.

Но если задача С получит первой право на обновление счета, то этого не произойдет. Таким образом, остаток на счете зависит от того, какой задаче В или С первой удастся сделать запрос к задаче А. Более того, мы можем выполнять задачи В и С несколько раз с одними и теми же значениями, и при этом иногда запрос задачи В будет произведен на какую-то долю секунды быстрее, чем запрос задачи С, а иногда — наоборот.

Очевидно, что необходимо организовать надлежащую координацию действий. Для координации задач, выполняемых параллельно, требуется обеспечить связь между ними и синхронизацию их работы. При некорректной связи или синхронизации обычно возникает четыре типа проблем. Какая задача в нашей программе поддержки электронного банка первой получит доступ к остатку на счете, определяется результатом работы планировщика задач операционной системы, состоянием процессоров, временем ожидания и случайными причинами.

И какое значение в этом случае должен сообщать банк в качестве реального остатка на счете? Итак, несмотря на то, что мы хотели бы, чтобы наша программа позволяла одновременно обрабатывать множество операций по снятию денег со счета и вложению их на депозит, нам нужно координировать эти задачи в случае, если окажется, что операции снятия и вложения денег должны быть применены к одному и тому же счету.

Всякий раз когда задачи одновременно используют модифицируемый ресурс, к ресурсному доступу этих задач должны быть применены определенные правила и стратегии. Например, в нашей программе поддержки банковских операций со счетами мы могли бы всегда выполнять любые операции по вложению денег до выполнения каких бы то ни было операций по их снятию. Мы могли бы установить правило, в соответствии с которым доступ к счету одновременно могла получать только одна транзакция. И если окажется, что к одному и тому же счету одновременно обращается сразу несколько транзакций, их необходимо задержать, организовать их выполнение в соответствии с некоторым правилом очередности, а затем предоставлять им доступ к счету по одной в порядке очереди.

Такие правила организации позволяют добиться надлежащей синхронизации действий. Такое планирование, при котором одна или несколько задач должны ожидать до тех пор, пока не произойдет некоторое событие или не создадутся определенные условия, м ожет оказаться довольно непростым для реализации.

Во-первых, ожидаемое событие или условие должно отличаться регулярностью. Во-вторых, между задачами следует наладить связи.

Если одна или несколько задач ожидают сеанса связи до своего выполнения, то в случае, если ожидаемый сеанс связи не состоится, состоится слишком поздно или не полностью, эти задачи могут так никогда и не выполниться.

И точно так же, если ожидаемое событие или условие, которое по нашему мнению должно произойти или наступить , но в действительности не происходит или не наступает , то приостановленные нами задачи будут вечно находиться в состоянии ожидания.

Если мы приостановим одну или несколько задач до наступления события или условия , которое никогда не произойдет, возникнет ситуация, называемая бесконечной отсрочкой indefinite postponement. Возвращаясь к нашему примеру электронного банка, предположим, что, если мы установим правила, предписывающие всем задачам снятия денег со счета находиться в состоянии ожидания до тех пор, пока не будут выполнены все задачи вложения денег на счет, то задачи снятия денег рискуют стать бесконечно отсроченными.

Мы исходили из предположения о гарантированном существовании задач вложения денег на счет. Но если ни один из запросов на пополнение счетов не поступит, то что тогда заставит выполниться задачи снятия денег? И, наоборот, что, если будут без конца поступать запросы на пополнение одного и того же счета? Такая ситуация также может вызвать бесконечную отсрочку задач снятия денег. Бесконечная отсрочка возникает при отсутствии задач вложения денег на счет или их постоянном поступлении. Необходимо также предусмотреть ситуацию, когда запросы на вложение денег поступают корректно, но нам не удается надлежащим образом организовать связь между событиями и задачами.

По мере того как мы будем пытаться скоординировать доступ параллельных задач к некоторому общему ресурсу данных, следует предусмотреть все ситуации, в которых возможно создание бесконечной отсрочки. Методы, позволяющие избежать бесконечных отсрочек, рассматриваются в главе 5. Для демонстрации взаимоблокировки предположим, что в нашей программе поддержки электронного банка три задачи работают не с одним, а с двумя счетами. Вспомним, что задача А получает запросы от задачи В на снятие денег со счета, а от задачи С — запросы на вложение денег на депозит.

Задачи А, В и С могут выполняться параллельно. Однако задачи В и С могут обновлять одновременно только один счет. Предположим также, что задача В имеет монопольный доступ к счету 1, а задача С — монопольный доступ к счету 2.

При этом задаче В для выполнения соответствующей обработки также нужен доступ к счету 2 и задаче С — доступ к счету 1. Задача В удерживает счет 1, ожидая, пока задача С не освободит счет 2. Аналогично задача С удерживает счет 2, ожидая, пока задача В не освободит счет 1. Тем самым задачи В и С рискуют попасть в тупиковую ситуацию , которую в данном случае можно назвать взаимоблокировкой deadlock.

Ситуация взаимоблокировки между задачами В и С схематично показана на рис. Форма взаимоблокировки в данном случае объясняется наличием параллельно выполняемых задач, имеющих доступ к совместно используемым данным, которые им разрешено обновлять. Здесь возможна ситуация, когда каждая из задач будет ожидать до тех пор, пока другая не освободит доступ к общим данным общими данными здесь являются счет 1 и счет 2.

Обе задачи имеют доступ к обоим счетам. Поскольку задача В не может освободить счет 1, пока не получит К туп к счету 2, а задача С не может освободить счет 2, пока не получит доступ к счету 1, программа обслуживания счетов электронного банка будет оставаться заблокированной. Обратите внимание на то, что задачи В и С могут ввести в состояние бесконечной отсрочки и другие задачи если таковые имеются в системе.

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

Их процессоры могут иметь различную архитектуру, обрабатывать слова различной длины и использовать различные машинные языки. Помимо разных операционных систем, компьютеры могут различаться используемыми стратегиями планирования и системами приоритетов.

Хуже того, все системы могут различаться параметрами передачи данных. Это делает обработку ошибок и исключительных ситуаций исключений особенно трудной. Неоднородность системы может усугубляться и другими различиями. Например, может возникнуть необходимость организации совместного использования данных программами, написанными на различных языках или разработанных с использованием различных моделей ПО. Это вносит проблемы межъязыковой связи.

И даже если распределенная или параллельная среда не является гетерогенной, остается проблема взаимодействия между несколькими процессами или потоками. Поскольку каждый процесс имеет собственное адресное пространство, то для совместного использования переменных, параметров и значений, возвращаемых функциями, необходимо применять технологию межпроцессного взаимодействия interprocess communication — IPC , или МПВ-технологию.

И хотя реализация МПВ-методов необязательно является самой трудной частью разработки системы ПО, тем не менее они образуют дополнительный уровень проектирования, тестирования и отладки в создании системы. POSIX-спецификация поддерживает пять базовых механизмов, используемых для реализации взаимодействия между процессами:.

Каждый из этих механизмов имеет достоинства, недостатки, ловушки и тупики, которые проектировщики и разработчики ПО должны обязательно учитывать, если хотят создать надежную и эффективную связь между несколькими процессами. Организовать взаимодействие между несколькими потоками которые иногда называются облегченными процессами обычно проще, чем между процессами, так как потоки используют общее адресное пространство.

Это означает, что каждый поток в программе может легко передавать параметры, принимать значения, возвращаемые функциями, и получать доступ к глобальным данным.

Необходимо отметить, что перечисленные выше проблемы характерны как для распределенного, так и для параллельного программирования. Несмотря на то что системы с исключительно параллельной обработкой отличаются от систем с исключительно распределенной обработкой, мы намеренно не проводили границу между проблемами координации в распределенных и параллельных системах. Частично мы можем объяснить это некоторым перекрытием существующих проблем, и частично тем, что некоторые решения проблем в одной области часто применимы к проблемам в другой.

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

Это означает, что на практике проектировщик или разработчик ПО будет теперь все чаще сталкиваться с проблемами распределения и параллелизма. Вот потому-то мы и рассматриваем все эти проблемы в одном пространстве. В этом случае подходит применение библиотеки PVM. И точно так же существуют конфигурации, в которых распределение может быть достигнуто лишь на одном компьютере за счет разбиения логики ПО на несколько процессов или потоков.

Комбинации параллельного и распределенного программирования, представленные в табл. Комбинации параллельного и распределенного программирования с различными конфигурациями аппаратного обеспечения.

Независимо от используемой конфигурации аппаратных средств, существует два базовых механизма, обеспечивающих взаимодействие нескольких задач: Эффективное использование обоих механизмов подробно рассматривается ниже в этой книге.

При совместной работе множества процессоров над решением некоторой задачи возможен отказ одного или нескольких процессоров. Каким в этом случае должно быть поведение ПО? Программа должна остановиться или возможно перераспределение работы?

Что случится, если при использовании мультикомпьютерной системы канал связи между несколькими компьютерами временно выйдет из строя? Что произойдет, если поток данных будет настолько медленным, что процессы на каждом конце связи превысят выделенный им лимит времени?

Как ПО должно реагировать на подобные ситуации? Если, предположим, во время работы системы, состоящей из 50 компьютеров, совместно работающих над решением некоторой проблемы, произойдет отказ двух компьютеров, то должны ли остальные 48 взять на себя их функции?

Если в нашей программе электронного банка при одновременном выполнении задач по снятию и вложению денег на счет две задачи попадут в ситуацию взаимоблокировки, то нужно ли прекратить работу серверной задачи? И что тогда делать с заблокированными задачами?

Что делать с частичными отказами или прерывистой работой? Подобные вопросы обычно не возникают при работе последовательных программ в одно-компьютерных средах. Иногда отказ системы является следствием административной политики или стратегии безопасности. Например, предположим, что система содержит подпрограмм, и некоторым из них требуется доступ к файлу для записи в него информации, но они по какой-то причине не могут его получить. В результате возможны взаимоблокировка, бесконечная отсрочка или частичный отказ.

А как быть, если некоторые подпрограммы блокируются из-за отсутствия у них прав доступа к нужным ресурсам? Насколько можно доверять обработанной информации, если в системе произошли сбои в оборудовании, отказ каналов связи или их работа была прерывистой? Тем не менее эти ситуации очень даже характерны можно сказать, являются нормой для распределенных или параллельных сред.

В этой книге мы рассмотрим ряд архитектурных решений и технологий программирования, которые позволят программному обеспечению системы справляться с подобными ситуациями. Сложность синхронизации или уровень связи между процессорами может потребовать таких затрат вычислительных ресурсов, что они отрицательно скажутся на производительности задач, совместно выполняющих общую работу. Как узнать, на сколько процессов, задач или потоков следует разделить программу?

И, вообще, существует ли оптимальное количество процессоров для любой заданной параллельной программы? Нетрудно предположить, что рассматриваемые числа зависят от конкретной программы.

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

Всегда необходимо отличать работу и ресурсы, задействованные в управлении параллельными аппаратными средствами, от работы, направленной на управление параллельно выполняемыми процессами и потоками в ПО. Предел числа программных процессов может быть достигнут задолго до того, как будет достигнуто оптимальное количество процессоров или компьютеров. И точно так же можно наблюдать снижение эффективности оборудования еще до достижения оптимального количества параллельно выполняемых задач.

Существует множество архитектурных решений, которые поддерживают параллелизм. Архитектурное решение можно считать корректным, если оно соответствует декомпозиции работ work breakdown structure — WBR программного обеспечения ДР ПО.

Параллельные и распределенные архитектуры могут быть самыми разнообразными. В то время как некоторые распределенные архитектуры прекрасно работают в Web-среде, они практически обречены на неудачу в среде с реальным масштабом времени. Например, распределенные архитектуры, которые рассчитаны на длинные временные задержки, вполне приемлемы для Web-среды и совершенно неприемлемы для многих сред реального времени. Достаточно сравнить распределенную обработку данных в Web-ориентированной системе функционирования электронной почты с распределенной обработкой данных в банкоматах, или автоматических кассовых машинах automated teller machine— ATM.

Задержка время ожидания , которая присутствует во многих почтовых Web-системах, была бы попросту губительной для таких систем реального времени, как банкоматы. Одни распределенные архитектуры имеются в виду некоторые асинхронные модели справляются с временными задержками лучше, чем другие. Кроме того, необходимо самым серьезным образом подходить к выбору соответствующих архитектур параллельной обработки данных. Например, методы векторной обработки данных наилучшим образом подходят для решения определенных математических задач и проблем имитационного моделирования, но они совершенно неэффективны в применении к мультиагентным алгоритмам планирования.

Распространенные архитектуры ПО, которые поддерживают параллельное и распределенное программирование, показаны в табл. Четыре базовые модели, перечисленные в табл. Разработчикам ПО необходимо подробно ознакомиться с каждой из этих моделей и их приложением к параллельному и распределенному программированию. Мы считаем своим долгом предоставить читателю введение в эти модели и дать библиографические сведения по материалам, которые позволят найти о них более детальную информацию.

В каждой работе или при решении проблемы лучше всего искать естественный или присущий им параллелизм, а выбранный тип архитектуры Должен максимально соответствовать этому естественному параллелизму. При тестировании последовательной программы разработчик может отследить ее логику в пошаговом режиме.

Если он будет начинать тестирование с одних и тех же данных при условии, что система каждый раз будет пребывать в одном и том же состоянии, то результаты выполнения программы или ее логические цепочки будут вполне предсказуемыми. Программист может отыскать ошибки в программе, используя соответствующие входные данные и исходное состояние программы, путем проверки ее логики в пошаговом режиме. Тестирование и отладка в последовательной модели зависят от степени предсказуемости начального и текущего состояний программы, определяемых заданными входными данными.

С параллельным и распределенным программированием все обстоит иначе. Здесь трудно воспроизвести точный контекст параллельных или распределенных задач из-за разных стратегий планирования, применяемых в операционной системе, динамически меняющейся рабочей нагрузки, квантов процессорного времени, приоритетов процессов и потоков, временных задержек при их взаимодействии и собственно выполнении, а также различных случайных изменений ситуаций, характерных для параллельных или распределенных контекстов.

Чтобы воспроизвести точное состояние в котором находилась среда при тестировании и отладке, необходимо воссоздать каждую задачу, выполнением которой была занята операционная система. При этом должен быть известен режим планирования процессорного времени и точно воспроизведены состояние виртуальной памяти и переключение контекстов. Кроме того, следует воссоздать условия возникновения прерываний и формирования сигналов, а в некоторых случаях — даже рабочую нагрузку сети. При этом нужно понимать, что и сами средства тестирования и отладки оказывают немалое влияние на состояние среды.

Это означает, что создание одинаковой последовательности событий для тестирования и отладки зачастую невозможно. Необходимость воссоздания всех перечисленных выше условий обусловлено тем, что они позволяют определить, какие процессы или потоки следует выполнять и на каких именно процессорах.

И хотя некоторые из этих проблем встречаются и в последовательном программировании, они не в силах зачеркнуть допущения, сделанные при построении последовательной модели. Тот уровень предсказуемости, который имеет место в последовательной модели, недоступен для параллельного программирования.

Это заставляет разработчика овладевать новыми тактическими приемами для тестирования и отладки параллельных и распределенных программ, а также требует от него поиска новых способов доказательства корректности его программ.

При создании документации на проектирование параллельного или распределенного ПО необходимо описать декомпозицию работ и их синхронизацию, а также взаимодействие между задачами, объектами, процессами и потоками. При этом проектировщики должны тесно контактировать с разработчиками, а разработчики — с теми, кто будет поддерживать систему и заниматься ее администрированием. В идеале это взаимодействие должно осуществляться по действующим стандартам.

Однако найти единый язык, понятный всем сторонам и позволяющий четко представить мультипарадигматическую природу всех этих систем, — трудно достижимая цель. Семь диаграмм, перечисленных в табл. В частности, UML-диаграмм деятельности, развертывания и состояний весьма полезны для описания взаимодействующего поведения параллельной и распределенной подсистем обработки данных. Поскольку UML — это фактический стандарт, используемый при создании взаимодействующих объектно-ориентированных и агентно-ориентированных проектов, при изложении материала в этой книге мы опираемся именно на него.

Описание обозначений и символов, используемых в перечисленных выше диаграммах, содержится в приложении А. UML-диаграммы, используемые при создании многопоточных, параллельных или распределенных программ. Диаграмма видов деятельности - разновидность диаграммы состояний, в которой большинство состояний или все представляют виды деятельности, а большинство переходов или все активизируются при выполнении некоторого действия в исходных состояниях.

Декомпозиция работ для MPI-интерфейса. Использование шаблонных функций для представления MPI-задач. Как упростить взаимодействие между MPI-задачами.

Визуализация проектов параллельных и распределенных систем. Проектирование компонентов для поддержки параллелизма. Как воспользоваться преимуществами интерфейсных классов. Подробнее об объектно-ориентированном взаимном исключении и интерфейсных классах. Пользовательские классы, создаваемые для обработки PVM-потоков данных. Объектно-ориентированные каналы и FIFO-очереди как базовые элементы низкого уровня. Понятие об агентно-ориентированном программировании. Активизация источников знаний с помощью потоков.

Первые шаги в программировании [Самоучитель]. Fiction Book Designer 3. Руководство по созданию книг. Writing a Simple Operating System —from Scratch. Mastering Algorithms with C. Основы алгоритмизации и программирования. Lina Lina 17 Довериться любви СИ книга классная.

About the Author: Сильвестр