Работаем на параллельном компьютере ParsytecCC/16
М. П. Крутиков
Фирма Parsytec (Германия) производит многопроцессорные вычислительные системы архитектуры MIMD. Машина Parsytec CC/16 представляет собой 16-процессорную систему, в которой имеется 16 узлов (по одному процессору на узел).
При ближайшем рассмотрении, выясняется, что каждый узел представляет собой ``нормальную'' машину, со своим жестким диском, своей оперативной памятью. Более того, на каждом узле запущена своя копия операционной системы. Что же позволяет считать эту машину параллельным суперкомпьютером? А вот что: все узлы оборудованы специальным коммуникационным устройством, которое позволяет осуществлять быстрый обмен информацией между узлами. Таким образом, появляется возможность синхронизации процессов, запущенных на разных узлах, и информационного обмена.
Итак, Parsytec CC - это 16 компьютеров, связанных быстрой сетью. Возможности параллельного исполнения задания опираются на работу с ``быстрыми связями''. Интерфейсом к параллельной системе является операционная система PARIX (точнее Embedded PARIX), позволяющая скрыть от пользователя детали синхронного запуска задач.
Что представляет собой узел? Каждый узел системы Parsytec CC/16 есть компьютер, построенный на процессоре PowerPC 604 фирмы Motorola, который работает на тактовой частоте 133Мгц. Стандартная материнская плата имеет PCI-слоты, в один из которых вставлена плата ``скоростной связи'' (High Speed Link). Кроме HSL, каждый узел имеет стандартный сетевой интерфейс Ethernet-TP. Кроме того, некоторые узлы оборудованы дополнительной периферией (см. ниже).
Каждый узел имеет свой SCSI жесткий диск, с которого он загружается. Размер оперативной памяти в нашей конфигурации - 32Мбайт на узел.
Два типа элементов составляют систему: узлы и роутеры. Выше мы познакомились с отдельным узлом. Узел - это машина, из которой ``торчит'' HSL. Этот HSL входит в один из портов роутера. Функцией роутера является коммутация пакетов информации между узлами. В роутере восемь портов, каждый из которых может замыкаться либо на узел, либо на другой роутер. Таким образом строится физическая конфигурация машины, которая задается количеством роутеров, количеством узлов, и топологией связей между узлами и роутерами. В системе Parsytec CC/16 имеется 16 узлов и 4 роутера.
Не все узлы равны между собой.
- P-node, процессорный узел. Имеет свой небольшой жесткий диск с системным ПО, контроллер Ethernet-TP и контроллер HSL. Непосредственно недоступен пользователю (нельзя, например, войти на него с помощью telnet или rlogin). В нашей системе таких узлов 13.
- IO-node, узел ввода-вывода. Помимо всего, что есть у P-node, оснащен дополнительной периферией (внешние диски, графический монитор, CD-ROM накопитель и др.). У нас три IO-node, один оснащен внешним SCSI-интерфейсом, на котором находятся внешние жесткие диски, другой - дополнительным контроллером Ethernet, к третьему может быть подключена графическая консоль.
- Наконец, один из IO-узлов является ``узлом входа'' (Entry node). Это тот IO-node, что оснащен дополнительным Ethernet-контроллером. Через этот интерфейс узел подключен к внешнему миру (внешней сети). Только этот узел непосредственно доступен пользователю. Сюда он попадает, когда делает telnet на систему Parsytec CC/16, и оказывается в среде ОС AIX.
На каждом узле функционирует операционная система AIX (эта UNIX-подобная операционная система разработана фирмой IBM для персональных компьютеров и рабочих станций на основе процессоров PowerPC). Сама по себе ОС AIX функционирует на отдельно стоящем узле и не может реализовать параллельную обработку задачи.
Для решения параллельных задач используется PARIX (Parallel extensions to UNIX), которая реализована в виде надстройки над ОС AIX. При обращении к ОС PARIX, последняя захватывает ресурсы всех процессоров в указанном разделе и запускает на них вашу прикладную задачу (о разделах смотри ниже).
Важно, что PARIX - это однозадачная система: если один пользователь запустил PARIX-приложение на разделе, то никакой другой пользователь уже не сможет запустить своего PARIX-приложения на данном разделе, покуда первое приложение не закончит свою работу и не освободит раздел.
С одной стороны, такой подход несомненно ограничивает пользователей, заставляя их строго координировать свои расчетные задачи. С другой же стороны, такая схема обеспечивает наиболее благоприятный режим для запущенного приложения.
Принята следующая модель представления многопроцессорной системы: все процессоры ``заполняют'' ячейки в некоем трехмерном ``ящике''. Именно: каждому процессору приписаны уникальные координаты (тройка целых положительных чисел). Так что с точки зрения пользователя процессор кроме своего порядкового номера имеет ``координаты''.
В трехмерном ящике с узлами не может быть дыр: если существует процессор с координатами (0,0,0) и существует (0,0,2), значит обязан существовать и (0,0,1). Кстати, узел (0,0,0) существует всегда (если в системе ненулевое количество процессоров).
Сие означает, что логическое пространство, занимаемое процессорами можно характеризовать положением угловых узлов. В нашей системе логическая конфигурация линейна: (0,0,0)-(15,0,0). Логическая конфигурация может быть (относительно легко) изменена. В принципе в системе с 16 процессорами возможны также конфигурации вида квадрата (0,0,0)-(4,4,0), (0,0,0)-(4,2,2) и др. Удобство той или иной конфигурации определяется в конечном счете характером решаемых задач (так, для расчетов матриц, вероятно, наиболее удобна конфигурация (0,0,0)-(4,4,0)).
Конечная трехмерная решетка, включающая в себя все процессоры данной машины называется основным разделом. Обычно основной раздел делится на несколько более мелких (и, возможно, перекрывающихся) разделов. Самым мелким, понятно, является раздел, состоящий из одного узла. Например, (0,0,0)-(15,0,0) у нас поделен на четыре четырехпроцессорных раздела (0,0,0)-(3,0,0), (4,0,0)-(7,0,0), (8,0,0)-(11,0,0) и (12,0,0)-(13,0,0) и шестнадцать однопроцессорных раздела. В общем случае, разделы могут перекрываться. Важнейшей характеристикой раздела является его размер, т.е. размер трехмерного ящика с узлами, входящими в данный раздел. Размер раздела (0,0,0)-(15,0,0) есть (4,1,1).
ОС PARIX может запускать приложения не только на основном разделе, но и на любом из логических разделов. Так, можно запустить задачу на четырехпроцессорном разделе. При этом останутся свободными три четырехпроцессорных раздела. На них также можно что-нибудь запустить. В вырожденном случае можно запустить одновременно 16 PARIX-приложений, но каждое, увы, будет иметь лишь один процессор. Как ведет себя PARIX, если разделы перекрываются? Так: если из двух перекрывающихся разделов один занят, то на другом не может быть запущено PARIX-приложение (блокируется).
И последнее (перед последующим). Ваша прикладная задача может узнать о параметрах раздела, на котором она запущена. Однако, точка отсчета раздела всегда транслируется в ноль, так что, приложение не может отличить, скажем, запущено оно на (0,0,0)-(3,0,0) или на (8,0,0)-(11,0,0). Оба случая для прикладной задачи будут выглядеть как раздел (0,0,0)-(3,0,0) с размером (4,1,1).
Прикладная задача, прежде чем приступить к выполнению расчета, должна позаботиться об организации межпроцессорных связей для обмена данными. Эти связи выглядят как коммуникационный канал (канал обмена данными) типа ``точка-точка'', то есть идет системный вызов ``создать соединение между таким-то узлом и таким-то узлом''. Топология создаваемой системы определяется исключительно характером конкретной задачи. Так, в одном случае полезно организовать ``звезду'', а в другом - ``кольцо''.
Еще раз подчеркнем отличие логических связей от физических:
- физические связи системы неизменны (определяются тем, как соединены между собой узлы и роутеры), тогда как логические связи создаются пользователями;
- каждый узел имеет лишь один HSL, тогда как количество логических связей одного узла не ограничено;
- в создании физических связей участвует роутер, логические же связи выглядят как соединение между узлами.
Немного выводов из представленного выше описания архитектуры системы. Итак, система представляет собой многопроцессорную машину с раздельной (не разделяемой!) оперативной памятью. Синхронизация и обмен данными между отдельными процессорами происходит по специальным быстрым коммуникационным каналам. Поэтому, необходимо в расчетном алгоритме находить разумный компромисс между объемом вычислительной работы и объемом передаваемых данных. В случае неразумно большого потока обмена возможно понижение производительности, обусловленное конечной (хоть и достаточно большой) пропускной способностью канала.
Задача должна строиться так, чтобы объем требуемой оперативной памяти не превышал 32Mb (имеется в виду та часть задачи, которая будет выполняться на отдельном узле). То, что в целом, в системе 32x16=512Мb оперативной памяти вовсе не означает, что вы можете работать с массивом размером 512Mb!
Следует ответственно подходить к разработке схемы коммуникации между узлами, поскольку от этого может сильно зависеть производительность.
Очень важно понимать конфигурацию системы. Так, если в задаче очень много дисковых операций, следует запускать ее на том разделе, где есть IO-node с теми дисками, с которыми система работает, иначе данные будут передаваться через внутреннюю сеть машины (не через HSL), что довольно медленно. Наоборот, если задача чисто расчетная следует избегать использования разделов с IO-узлами, поскольку эти узлы могут быть загружены обменом данными. Особенно неприятен в этом случае Entry-node, на котором запущенное PARIX-приложение будет конкурировать за процессорное время с задачами других пользователей: компиляция и отладка программ.
Прикладная программа должна быть написана так, чтобы ее можно было запустить на произвольном количестве процессоров (масштабируема), поскольку на каком именно разделе она будет выполняться определяется пользователем при ее запуске.
Наконец, должно быть ясно, что адаптация вашей программы под PARIX есть не очень простая задача, и здесь нельзя отделаться опцией компилятору (как в ConvexOS). Вопрос: а что будет, если кто-нибудь просто откомпилирует свою задачу, не внося в нее изменений? Ответ: она будет успешно откомпилирована, однако если ее запустить, то задача будет считаться параллельно (и независимо) от начала до конца на каждом из процессоров в разделе. Так что для 16-процессорного раздела вы получите 16 идентичных результатов. Скорость счета будет равна скорости счета на одном процессоре. Из этого должен последовать неизбежный вывод о том, что, увы, придется трудиться, если есть желание использовать все мощности системы Parsytec CC/16.
Зарегистрировавшись на машине, вы попадаете в знакомую среду командного интерпретатора
csh ОС UNIX (точнее - AIX). На машине есть все обычные для UNIX средства работы: редакторы
vi и
emacs, отладчики, компиляторы. Это и не удивительно - ведь вы попали на однопроцессорную UNIX-станцию, являющуюся Entry-узлом многопроцессорной машины.
Следующие, характерные для многопроцессорной системы, задачи вам предстоит решать:
- компиляция вашей программы для запуска под ОС PARIX
- запуск программы под управлением ОС PARIX
С точки зрения пользователя, обращение к возможностям ОС PARIX происходит с помощью команды px
px command
Собственно команда px модифицирует пользовательское окружение, так что command понимается уже как команда ОС PARIX. Например,
px man run
выдаст manual pages из ОС PARIX, в то время как просто команда man ... выдает справочную информацию по AIX.
Чтобы ваша прикладная программа могла быть запущена под управлением ОС PARIX необходимо, чтобы она была скомпилирована специальным образом. Чем же отличаются программы PARIX от программ AIX? Приложения PARIX используют другие библиотечные функции для операций ввода/вывода, а также специальные библиотечные функции (из библиотек PARIX).
- Операции ввода-вывода в приложении PARIX переопределены таким образом, что независимо от узла, на котором будет работать приложение, ввод-вывод относится к IO-узлу.
- Специальные библиотечные функции PARIX позволяют организовать межпроцессорное взаимодействие (синхронизацию и обмен данными по HSL).
Приложения AIX не будут работать, если их запустить на разделе PARIX, и наоборот, AIX не ``поймет'' запросов запущенного приложения PARIX. Так что PARIXу - PARIXово.
Parsytec CC/16 оснащен стандартными для AIX компиляторами языков C и FORTRAN. С помощью этих компиляторов вы можете создать как приложение для AIX, так и приложение для PARIX. Для приложений AIX вы используете команду
ancc -o test test.c
Тогда как для того, чтобы сделать исполняемый файл для PARIX, надо дать команду
px ancc -o test.px test.c
Как обычно, команда-префикс px модифицирует следующую за ней команду так, что она превращается в команду ОС PARIX.
Отметим, что по соглашению исполняемые файлы PARIX имеют суффикс .px. Это позволяет отличать их от приложений, скомпилированных для AIX.
Компилятор языка FORTRAN вызывается командой f77. Если вы компилируете PARIX приложение, следует использовать команду px f77, например
px f77 -o test.px test.f
Разделом называется набор процессоров, выделенных в исключительное владение данному пользователю (точнее, запущенному на этом разделе приложению пользователя). Обычно, раздел - это часть машины, но он также может быть и всей машиной. Разделы могут перекрываться: большой раздел может состоять из более мелких. При этом, если более мелкий раздел занят, то большой раздел недоступен: блокируется.
Разделы имеют атрибуты. Основным атрибутом является количество процессоров.
Каждый раздел может использовать Entry-узел и IO-узлы машины для операций ввода-вывода.
Управление разделами осуществляется командой OC PARIX nrm (Network Resource Manager). Для просмотра конфигурации разделов, используется команда
px nrm -pc
которая выводит список определенных в системе разделов и их атрибуты:
ultra10% px nrm -pc
Partition | Attributes | Servers
----------+------------+--------
p1 | |
earth | p16 |
east | p4 |
north | p4 |
south | p4 |
west | p4 |
Более подробную информацию даст команда
px nrm -pp
где будет видна привязка разделов к физической конфигурации системы:
ultra10% px nrm -pp
CC Configuration: Wed Jul 24 13:12:23 1996 edited by root@ultra10
CC ParsytecCC: - no init info -
Topologie = using file /epx/epx/nrm/system.rt, Dimensions (16,1,1),
Command Port 12544
Node ultra10 at position (0,0,0) with attributes ( master-epxd
IO-node )
Node cc001736 at position (1,0,0) with attributes ( P-node )
Node cc001737 at position (2,0,0) with attributes ( P-node )
Node cc002245 at position (3,0,0) with attributes ( IO-node )
Node cc002243 at position (4,0,0) with attributes ( IO-node )
Node cc001738 at position (5,0,0) with attributes ( P-node )
Node cc001739 at position (6,0,0) with attributes ( P-node )
Node cc002246 at position (7,0,0) with attributes ( P-node )
Node cc001732 at position (8,0,0) with attributes ( P-node )
Node cc001733 at position (9,0,0) with attributes ( P-node )
Node cc001734 at position (10,0,0) with attributes ( P-node )
Node cc001735 at position (11,0,0) with attributes ( P-node )
Node cc001740 at position (12,0,0) with attributes ( P-node )
Node cc001744 at position (13,0,0) with attributes ( P-node )
Node cc001743 at position (14,0,0) with attributes ( P-node )
Node cc001742 at position (15,0,0) with attributes ( P-node )
Server filesrv with command line (/epx/bin/dserver -h)
Partition p1: corner atoms = (0,0,0) (0,0,0)
servers = ( )
Partition earth: attributes = ( p16 ), corner atoms = (0,0,0)
(15,0,0)
servers = ( )
Partition east: attributes = ( p4 ), corner atoms = (0,0,0)
(3,0,0)
servers = ( )
Partition north: attributes = ( p4 ), corner atoms = (4,0,0)
(7,0,0)
servers = ( )
Partition south: attributes = ( p4 ), corner atoms = (8,0,0)
(11,0,0)
servers = ( )
Partition west: attributes = ( p4 ), corner atoms = (12,0,0)
(15,0,0)
servers = ( )
Следующая команда
px nrm -pa
показывает статус разделов (занят/свободен) и имя пользователя, занявшего раздел. Разделы, помеченные звездочкой являются свободными:
ultra10% px nrm -pa
CC ParsytecCC:
Partition | Used by | Since
----------+--------------+-------------------------
p1 | east |
earth | east |
east | mike@ultra10 | Sat Nov 16 22:52:39 1996
north | * | Mon Nov 11 14:31:58 1996
south | * | Mon Nov 11 14:31:58 1996
west | * | Mon Nov 11 14:31:58 1996
Из данной таблицы видно, что раздел
east занят пользователем
mike. При этом, блокируется раздел
earth, т.к. он перекрывается с
east (раздел
earth является основным разделом и, естественно, он блокируется при запуске приложения на любом из подразделов), а также блокирован раздел
p1, т.к. этот однопроцессорный раздел содержит узел из раздела
east. Свободными остались три четырехпроцессорных раздела
north,
south и
west.
Другой способ представления той же информации дает команда
px nrm -pm
которая представляет систему наглядно в виде матрицы, где элементу соответствует один процессор:
ultra10% px nrm -pm
CC ParsytecCC:
Actual users of CC ParsytecCC:
A : mike@ultra10
Allocation of CC ParsytecCC:
AAAA************
Для запуска PARIX-приложения используется команда
run. При этом вы обязательно должны указать раздел, на котором должно быть запущено приложение.
Раздел можно именовать либо явно (тем именем, которое присвоено разделу администратором - см. px nrm -pc), либо неявно - указанием атрибутов раздела. Последнее более удобно, так как вы можете просто сказать, что ``требуется раздел с 4 процессорами'', и система выберет вам первый свободный 4-процессорный раздел.
Например
px run -a earth hello.px
Запускает PARIX-приложение hello.px на разделе с именем earth,
px run -a p4 hello.px
Запускает ту же программу на 4-х процессорном разделе.
Отметим, что команда run занимает указанный раздел, так что он (вместе с перекрывающимися разделами) становится недоступен для запуска других приложений PARIX.
По окончании PARIX-приложения,
run автоматически освобождает занятый раздел, так что он становится доступен для других PARIX-приложений.
Однако в ряде случаев (при аварийном завершении) раздел может остаться занятым. То есть, несмотря на то, что никакое приложение не исполняется на разделе, он остается недоступен для других пользователей. Поэтому будьте очень внимательны, и убедитесь, что уходя из системы, вы не оставили блокированных за вами разделов. Используйте для этого команду px nrm -pa. Разблокировать раздел можете либо вы сами, либо системный администратор.
Для явного освобождения раздела дайте команду PARIX nrm -f, например
px nrm -f earth
Отметим, что при освобождении раздела требуется указать имя раздела (а не его атрибуты).
Напомним, что приложение может узнать о конфигурации раздела, на котором оно запущено. Более того, нормальное PARIX-приложение обязательно использует эту информацию для организации взаимодействия между процессорами. Некоторые приложения требуют жестких ограничений на конфигурацию своего раздела. Например, приложение может проверять количество процессоров в разделе и завершать свою работу в случае, если количество процессоров меньше 4. Можно ли запустить такое приложение на 2-процессорном разделе? Да, можно.
PARIX позволяет организовывать виртуальную конфигурацию раздела. Так, можно потребовать, чтобы раздел, который имеет размеры (2,1,1) выглядел для приложения как раздел (2,2,1). Такая процедура называется организацией виртуального раздела.
Существует ограничение: каждый физический процессор может эмулировать не более 16 виртуальных. Так что на Parsytec CC/16 нельзя организовать виртуальный раздел с числом процессоров более 256.
Когда полезны виртуальные разделы?
- При отладке. Разумно отлаживать программы на малых физических разделах (чтобы другие пользователи могли отлаживать свои программы параллельно на других разделах). При этом можно эмулировать крупный раздел.
- При особых требованиях приложения к конфигурации раздела. Так, если приложение требует квадратной конфигурации (4,4,1), можно на имеющимся линейном 16-процессорном разделе создать виртуальный ``квадратный''.
Для создания виртуального раздела используются аргументы к команде run:
px run -a earth 4 2 2 test.px
запускает приложение на физическом разделе earth, но приложение ``видит'' виртуальный раздел с конфигурацией (4,2,2).
Принята следующая модель работы PARIX-приложения.
- При запуске на каждом узле стартует одна и та же программа
- затем она определяет свое положение в решетке раздела и
- организует обмен данными с другими своими копиями
На каждом узле имеется набор глобальных данных (доступных программе), которые определяют положение узла в разделе. Именно
- количество процессоров в разделе
- идентификатор данного процессора
- размеры решетки раздела
- положение данного процессора в решетке (координаты)
Обмен данных основан на концепции виртуальных связей между процессорами, которые образуют каналы ``точка-точка'' между любыми процессорами. Набор созданных виртуальных связей задает виртуальную топологию (решетка, конвейер, дерево, гиперкуб).
В PARIX связи могут быть одного из следующих трех видов:
- Синхронный канал. Это естественный для архитектуры Parsytec CC тип коммуникационного канала. Процессы, связанные синхронным каналом, синхронизуются при обмене данных: если одна сторона еще не готова к обмену данными, то другая будет ждать готовности. Следующие системные вызовы относятся к синхронным каналам: Send, Recv, Select, SendLink, RecvLink.
- Синхронная ``случайная'' передача. Это единственный способ передачи данных, при котором не требуется создавать коммуникационный канал. Данные передаются по системным каналам. Однако, при большом размере сообщения библиотечные вызовы автоматически создают виртуальный канал, с целью повышения скорости обмена. Для сообщений данного типа PARIX предоставляет системные вызовы SendNode и ReceiveNode.
- Асинхронный канал. Такой канал может осуществлять обмен данными не прерывая вычислений на узле. Поэтому канал такого типа улучшает кпд процессора. Прием/передача выполняются с буферизацией как на стороне передатчика, так и на стороне приемника. Следующие системные вызовы обслуживают асинхронные каналы: AInit, ASend, ARecv, ASync, AInfo, AExit
Начнем с классического примера: программы ``hello, world''.
#include < stdio.h>
int main() {
printf("Hello, world\n");
return 0;
}
Теперь надо построить PARIX-приложение. Для этого даем команду
px ancc -o hello.px hello.c
Теперь мы получили исполняемый файл hello.px, который можно запустить. Действительно, команда
px run -a p4 hello.px
запустит PARIX-приложение на разделе из 4-х процессоров и вы получите четыре строчки (ответит каждый процессор) Hello, world
Теперь немного модифицируем программу.
#include < stdio.h>
#include < epx/root.h>
int main() {
int ID;
ID=GET_ROOT()-> ProcRoot-> MyProcID;
printf("Hello, world! This is processor %d.\n",ID);
return 0;
}
Скомпилируем программу и запустим. Каждый процессор сообщит свой номер. На этом простом примере демонстрируется важное свойство PARIX: на каждом узле изначально запущены идентичные приложения. Но поведение процесса изменяется в соответствии с позицией процессора в решетке раздела. Функция GET_ROOT осуществляет доступ к (глобальным) данным о конфигурации раздела и положении текущего узла в решетке. Эта функция возвращает указатель на данные следующей структуры:
typedef struct {
int MyProcID; /* my processor number */
int MyX; /* my X coordinate */
int MyY; /* my Y coordinate */
int MyZ; /* my Z coordinate */
int nProcs; /* Number of processors */
int DimX; /* array dimension in X direction */
int DimY; /* array dimension in Y direction */
int DimZ; /* array dimension in Z direction */
} RootProc_t;
Эти данные не являются независимыми, т.к. справедливо следующее
MyProcID = (MyZ * DimX * DimY) + (MyY * DimX) + MyX
nProcs = Dimx * DimY * DimZ
Эта информация позволяет также вычислить идентификаторы соседних процессоров.
Более содержательные примеры см. в каталоге /epx/epx/examples.
Приведем простые программы на языке FORTRAN
C
C Hello, world!
C
PROGRAM HELLO
WRITE (*,*) 'Hello, world!'
STOP
END
Теперь надо построить PARIX-приложение. Для этого даем команду
px f77 -o hello.px hello.f
Теперь мы получили исполняемый файл hello.px, который можно запустить. Действительно, команда
px run -a p4 hello.px
запустит PARIX-приложение на разделе из 4-х процессоров и вы получите четыре строчки (ответит каждый процессор) Hello, world!
Теперь немного модифицируем программу.
C
C Hello, world! (Variant 2)
C
PROGRAM HELLO
INTEGER MYPROCID
ID=MYPROCID()
WRITE (*,*) 'Hello, world! This is processor ',ID,'.'
STOP
END
Скомпилируем программу и запустим. Каждый процессор сообщит свой номер.
Более содержательные примеры ищите в каталоге /epx/epx/examples/f77.
PARIX предоставляет специальные библиотечные функции для упрощения работы с процессами.
В рамках одного узла можно организовать несколько ветвей процесса (threads). Каждая ветвь выполняется параллельно. Все созданные ветви одного процесса имеют доступ к глобальным данным процесса. Говорят, что все ветви исполняются в рамках одного контекста. Каждая ветвь имеет свой собственный стек.
Понятие ветви является основным для модели программирования в симметричных мультипроцессорных системах (например Convex) и должно быть уже известно тем пользователям, кто создавал параллельные приложения для Convex.
Функция CreateThread создает новую ветвь процесса. Как обычно, стандартным методом синхронизации ветвей одного процесса является механизм семафоров.
Другим элементом параллельного программирования является создание нового контекста. В любой момент некоторая ветвь процесса может загрузить и запустить новый процесс (т.е. контекст), со своим собственным кодом, глобальными данными, и начальной ветвью. Породившая ветвь будет ожидать окончания выполнения запущенного контекста. Новый контекст создается функцией Execute.
Типичным приемом в параллельном программировании является следующий: на каждом процессоре запускается начальное приложение, которое определяет свое положение, и в зависимости от результата запускает тот или иной контекст.
- Документация по ОС PARIX (EPX) доступна в читальном зале центра
- Ее электронный вариант (в формате PostScript) можно взять с гипертекстового сервера центра: http://www.csa.ru/CSA/tutor/epx.ps(3Mb)
- On-line документация доступна через команду px man
Приведем список функций:
AExit
AINIT
AInfo
AInit
ARecv
ASend
ASync
AbortServer
AddHead
AddTail
AddTop
AddTop_Data
BreakLink
ChangePriority
CondSelect
CondSelectList
ConnectLink
CreateSem
CreateThread
DestroySem
Execute
Free2DGrid
Free2DTorus
Free3DGrid
Free3DTorus
FreeClique
FreeDeb
FreeHCube
FreePipe
FreeRing
FreeStar
FreeTop
FreeTree
GETGLOBAL
GET_ROOT
Get2DGrid_Data
Get2DTorus_Data
Get3DGrid_Data
Get3DTorus_Data
GetClique_Data
GetDeb_Data
GetGlobId
GetHCube_Data
GetLink
GetLinkCB
GetLocal
GetPipe_Data
GetPriority
GetRing_Data
GetStar_Data
GetTop_Data
GetTree_Data
InitList
InitSem
LIST
LogError
Make2DGrid
Make2DTorus
Make3DGrid
Make3DTorus
MakeClique
MakeDeb
MakeHCube
MakeLink
MakePipe
MakeRTree
MakeRing
MakeStar
MakeTree
NewTop
PostInsert
PreInsert
ReceiveOption
ReceiveOption_B
Recv
RecvLink
RecvNode
RemHead
RemTail
Remove
SELECT
SEMAPHORES
SEND
SENDNODE
SearchList
Select
SelectList
Send
SendLink
SendNode
SetLocal
Signal
StartThread
TIME
TIME
TOPOLOGY
TOPOLOGY
Terminate
TestWait
TimeAfter
TimeAfterOption
TimeAfterOption_B
TimeNow
TimeWait
VIRT_TOP
Virt_Top
Wait
WaitThread
WalkList