Опубликован: 22.04.2008 | Доступ: свободный | Студентов: 527 / 50 | Оценка: 4.50 / 4.75 | Длительность: 06:55:00
Специальности: Программист
Лекция 3:

Высокоуровневый язык параллельного программирования MC#

< Лекция 2 || Лекция 3: 123 || Лекция 4 >
Аннотация: Предметом изучения данной лекции является высокоуровневый язык параллельного программирования MC#. Рассматривается модель программирования языка MC#: async- и movable-методы, каналы, обработчики, связки, а также уделено внимание синхронизации в языке MC#

Язык параллельного программирования MC# предназначен для написания программ, работающих на всём спектре параллельных архитектур - от многоядерных процессоров до Grid-сетей. Единственное требование к таким системам со стороны MC# - на них должна быть установлена среда исполнения CLR (Common Language Runtime) с соответствующим набором библиотек. На машинах с операционной системой Windows реализацией такой среды является Microsoft .NET Framework, а на машинах с операционной системой Linux - система Mono (http://www.mono-project.com), которая является свободной реализацией платформы .NET для Unix-подобных систем.

Язык MC# является адаптацией и развитием базовых идей языка Polyphonic C# на случай параллельных и распределенных вычислений. Язык Polyphonic C# был разработан в 2002г. в Microsoft Research Laboratory (г. Кембридж, Великобритания) Н. Бентоном (N. Benton), Л. Карделли (L. Cardelli) и Ц. Фурнье (C. Fournet). Целью его создания было добавление высокоуровневых средств асинхронного параллельного программирования в язык C# для использования в серверных и клиент-серверных приложениях на базе Microsoft .NET Framework.

Ключевая особенность языка Polyphonic C# заключается в добавлении к обычным, синхронным методам, так называемых "асинхронных" методов, которые предназначены играть в (многопоточных) программах две основные роли:

  1. автономных методов, предназначенных для выполнения базовой вычислительной работы, и исполняемых в отдельных потоках, и
  2. методов, предназначенных для доставки данных (сигналов) обычным, синхронным методам.

Для синхронизации нескольких асинхронных методов, а также асинхронных и синхронных методов, в язык C#, кроме того, были введены новые конструкции, получившие название связок (chords).

При этом исполнение Polyphonic C#-программ, по замыслу авторов этого языка, по-прежнему, предполагалось либо на одной машине, либо на нескольких машинах, с зафиксированными на них асинхронными методами, взаимодействующими между собой с использованием средств удаленного вызова методов (RMI - Remote Method Invocation), предоставляемых библиотекой System.Runtime.Remoting платформы .NET.

В случае языка MC#, программист может предусмотреть исполнение автономных асинхронных методов либо локально, либо удаленно. В последнем случае, метод может быть спланирован для исполнения на другой машине, выбираемой двумя способами: либо согласно явному указанию программиста (что не является типичным случаем), либо автоматически (обычно, на наименее загруженном узле кластера или машине Grid-сети). Взаимодействие асинхронных методов, в рамках языка MC#, реализуется посредством передачи сообщений с использованием каналов и обработчиков канальных сообщений. Эти каналы и обработчики определяются в MC#-программах с помощью связок в стиле языка Polyphonic C#.

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

3.1. Модель программирования языка MC#: async- и movable-методы, каналы, обработчики связки

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

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

Разделение всех методов в программе на обычные (синхронные) и асинхронные (в том числе, на те, которые могут быть перенесены для исполнения на другие машины) производится программистом с использованием специальных ключевых слов async и movable. (В языке MC#, семантика и использование ключевого слова async полностью совпадает с использованием этого слова в языке Polyphonic C# за тем исключением, что в MC# async-методы не могут встречаться в связках - см. об этом ниже).

Async- и movable-методы являются единственным средством создания параллельных процессов (потоков) в языке MC#.

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

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

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

Для синхронизации параллельных процессов в MC# используются связки (chords), определяемые в стиле языка Polyphonic C#.

3.2. Async- и movable-методы

Общий синтаксис определения async- и movable-методов в языке MC# следующий:

модификаторы { async | movable } имя_метода ( аргументы )
{
   < тело метода >
}

Ключевые слова async и movable располагаются на месте типа возвращаемого значения, поэтому синтаксическое правило его задания при объявлении метода в языке MC# имеет вид:

return-type ::= type | void | async | movable

Задание ключевого слова async означает, что при вызове данного метода он будет запущен в виде отдельного потока локально, т.е., на данной машине (возможно, на отдельном ядре процессора), но без перемещения на другую машину. Ключевое слово movable означает, что данный метод при его вызове может быть спланирован для исполнения на другой машине.

Отличия async- и movable-методов от обычных методов состоят в следующем:

  • вызов async- и movable-методов заканчивается, по существу, мгновенно (для последних из названных методов, время затрачивается только на передачу необходимых для вызова этого метода данных на удаленную машину),
  • эти методы никогда не возвращают результаты (о взаимодействии movable-методов между собой и с другими частями программы, см. Раздел 2.2 "Каналы и обработчики").

Соответственно, согласно правилам корректного определения async- и movable-методов:

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

Вызов movable-метода имеет две синтаксические формы:

  1. имя_объекта.имя_метода ( аргументы )

    (место исполнения метода выбирается Runtime-системой автоматически),

  2. имя_машины@имя_объекта.имя_метода ( аргументы )

    ( имя_машины задает явным образом место исполнения данного метода).

При разработке распределенной программы на языке MC# (т.е., при использовании в ней movable-методов и исполнении её на кластере или в Grid-сети), необходимо учитывать следующие особенности системы исполнения (Runtime-системы) MC#-программ.

Во-первых, объекты, создаваемые во время исполнения MC#-программы, являются, по своей природе статическими: после своего создания, они не перемещаются и остаются привязанными к тому месту (машине), где они были созданы. В частности, именно в этом месте (на этой машине) они регистрируются Runtime-системой, что необходимо для доставки канальных сообщений этим объектам и чтения сообщений с помощью обработчиков, связанных с ними (этими объектами).

Поэтому, первой ключевой особенностью языка MC# (а точнее, его семантики) является то, что, в общем случае, во время вызова movable-метода, все необходимые данные, а именно:

  1. сам объект, которому принадлежит данный movable-метод, и
  2. его аргументы (как ссылочные, так и скалярные значения) только копируются (но не перемещаются) на удаленную машину. Следствием этого является то, что все изменения, которые осуществляет (прямо или косвенно) movable-метод с внутренними полями объекта, проводятся с полями объекта-копии на удаленной машине, и никак не влияют на значение полей исходного объекта.

Если копируемый (при вызове его movable-метода) объект обладает каналами или обработчиками (или же просто, они являются аргументами этого movable-метода), то они также копируются на удаленную машину. Однако, в этом случае, они становятся "прокси"-объектами для исходных каналов и обработчиков.

< Лекция 2 || Лекция 3: 123 || Лекция 4 >