rtsIDr (1158449), страница 11
Текст из файла (страница 11)
Функция endpl_ определяет завершение параллельного цикла и слияние параллельных ветвей в исходную (родительскую) ветвь. В момент завершения параллельного цикла все созданные в нём объекты, кроме статических, автоматически уничтожаются (т.е. параллельный цикл является программным блоком, начинающимся с обращения к функции crtpl_ , см.п.8).
Система поддержки допускает завершение программы с помощью функции lexit_ (см. п. 2) при выполнении любого параллельного цикла без его предварительного завершения функцией endpl_ .
После выхода из параллельного цикла ссылка на него считается неопределённой и не может быть использована в дальнейшем при обращении к системе поддержки как ссылка на этот параллельный цикл.
Функция возвращает нулевое значение.
9.6Задание информации о зависимостях по данным между витками параллельного цикла
Разбиение выполнения параллельного цикла на части (необходимое для асинхронного обмена границами распределённых массивов, динамического перераспределения вычислений между процессорами и т. д.) влечёт изменение порядка выполнения его витков, что при наличии зависимостей по данным между витками может привести к неверным вычислениям. Для правильной организации разбиения витков цикла на порции системе поддержки необходима информация о всех точках вида (I1+D1, … , In+Dn), значения вычисляемой переменной в которых требуются для определения её значения в точке (I1, ... , In) (n – размерность цикла, все Di – целые числа). Предполагается, что хотя бы два значения Di отличны от нуля (информация о точках, для которых число ненулевых Di не превосходит единицы, системе поддержки не требуется).
Информация о каждой точке приведённого выше вида сообщается системе поддержки отдельным обращением к функции
| long pldpnd_( | LoopRef | *LoopRefPtr, |
| *LoopRefPtr | | ссылка на параллельный цикл. |
| DependCodeArray | | массив, i-й элемент которого содержит код зависимости по данным между витками цикла по его (i+1)-му измерению. |
Коды зависимостей по данным, задаваемые в i-м элементе массива DependCodeArray, могут принимать значения:
| 0 | | нет зависимости по данным (Di+1 равно нулю); |
| 1 | | обратная зависимость по данным (Di+1 положительно); |
| 2 | | прямая зависимость по данным (Di+1 отрицательно). |
Информация о нескольких точках сообщается системе поддержки несколькими обращениями к функции pldpnd_. Все обращения к этой функции должны предшествовать отображению параллельного цикла функцией mappl_ (см. п. 9.2).
Отсутствие обращений к функции pldpnd_ перед отображением цикла означает, что между его витками нет зависимостей по данным, ограничивающих выполнение цикла по частям.
Функция возвращает нулевое значение.
Замечание. Если по измерению цикла осуществляется разбиение его выполнения на части, то такое измерение будем называть квантуемым. Выбор квантуемых измерений система поддержки осуществляет с приоритетом измерений с большими номерами (их индексные переменные меняются быстрее) и руководствуясь критерием: в правой части оператора присваивания не может фигурировать точка, совокупность квантуемых измерений которой содержит два или более измерения с разнонаправленными зависимостями по данным (для измерений с одинаковыми знаками шагов изменения их индексных переменных) или с одноправленными зависимостями по данным (для измерений с разными знаками шагов изменения их индексных переменных).
10Представление программы в виде соовокупности параллельно выполняющихся подзадач
Параллельной подзадачей будем называть пару (<абстрактная машина>, <процессорная подсистема>), а группой подзадач представление абстрактной машины, каждому элементу которого поставлена в соответствие процессорная подсистема. Параллельная подзадача находится в состоянии выполнения (активна) на процессоре, входящем в состав её процессорной подсистемы, если абстрактная машина подзадачи является текущей. На любом процессоре всегда выполняется ровно одна подзадача с отображённой на него абстрактной машиной (текущей).
Создание подзадач может быть осуществлено с помощью рассмотренных в п. 5 функций отображения представления абстрактной машины в процессорную подсистему (distr_, redis_, mdistr_, mredis_). Активизация созданных таким образом подзадач осуществляется при входе в виток параллельного цикла.
Рассмотрим теперь создание параллельных подзадач путем явного задания соответствия <абстрактная машина> <процессорная подсистема> и способ их (подзадач) активизации.
10.1Отображение абстрактной машины (создание подзадачи)
| long mapam_ ( | AMRef | *AMRefPtr, |
| *AMRefPtr | | ссылка на отображаемую абстрактную машину. |
| *PSRefPtr | | ссылка на процессорную подсистему, определяющую состав выделяемых абстрактной машине процессоров (область выполнения создаваемой подзадачи). |
Для успешного создания подзадачи её абстрактная машина и процессорная система должны удовлетворять условиям:
-
Абстрактная машина, заданная ссылкой *AMRefPtr, обязана принадлежать представлению родительской абстрактной машины, созданному в текущей подзадаче, и должна быть прямым или косвенным потомком текущей абстрактной машины;
-
Родительская абстрактная машина должна быть отображена.
Допускается повторное отображение (переотображение) абстрактной машины, не имеющей потомков (абстрактной машины, соответствующей листу дерева абстрактных машин). Нельзя переотобразить абстрактную машину, если она принадлежит представлению родительской абстрактной машины, отображённому функцией distr_ (mdistr_).
Функция возвращает нулевое значение.
10.2Начало выполнения (активизация, пуск) подзадачи
long runam_ (AMRef *AMRefPtr);
*AMRefPtr ссылка на абстрактную машину запускаемой подзадачи.
Для успешного запуска подзадачи её абстрактная машина должна принадлежать одному из представлений текущей абстрактной машины.
После запуска подзадачи её абстрактная машина и процессорная система становятся текущими. Вместе со сменой текущей процессорной системы осуществляется изменение и внутренних номеров центрального процессора и процессора ввода/вывода (каждая процессорная система имеет собственные центральный процессор и процессор ввода/вывода).
Функция возвращает значение:
| 0 | | запуск подзадачи не выполнен (текущий процессор не принадлежит процессорной системе запускаемой подзадачи); |
| 1 | | запуск подзадачи выполнен. |
10.3Завершение выполнения (останов) текущей подзадачи
long stopam_ (void);
После выполнения функции stopam_ текущей становится абстрактная машина, родительская по отношению к абстрактной машине остановленной подзадачи (абстрактная машина подзадачи, активизировавшей остановленную подзадачу). Аналогично, текущей станет процессорная система, подсистемой которой является процессорная система остановленной подзадачи.
Нельзя остановить подзадачу при выполнении параллельного цикла. Нельзя также остановить начальную подзадачу (подзадачи, породившей её, не существует).
Система поддержки допускает завершение программы с помощью функции lexit_ (см. п. 2) при выполнении любой подзадачи без предварительного её останова функцией stopam_ .
При останове подзадачи все объекты (кроме статических), созданные с момента её активизации, автоматически уничтожаются, т.е. точки пуска и останова подзадачи определяют программный блок (см.п.8).
Функция возвращает нулевое значение.
11Редукция
Редукция это вычисление заданной функции (редукционной) с использованием в качестве её аргументов значений переменной (редукционной), полученных на разных процессорах, выполнявших различные ветви параллельной программы. После выполнения редукции значение редукционной переменной станет одинаковым для всех процессоров и равным значению, возвращенному редукционной функцией.
В целях оптимизации редукция выполняется над редукционной группой совокупностью редукционных переменных, с каждой из которых связана своя редукционная операция.
11.1Создание редукционной переменной
В качестве редукционной переменной может выступать:
-
скалярная переменная;
-
элемент "обычного" (размноженного по всем процессорам) массива;
-
одномерный "обычный" массив.
В общем случае считается, что редукционная переменная представлена одномерным массивом, а редукционная операция осуществляется над каждым его элементом.
Создание редукционной переменной это описание одномерного массива как редукционной переменной, осуществляемое с помощью следующей функции:
| RedRef crtred_ ( | long | *RedFuncNumbPtr, |
| *RedFuncNumbPtr | | номер редукционной операции. |
| RedArrayPtr | | указатель на редукционную переменную-массив. |
| *RedArrayTypePtr | | тип элементов редукционной переменной-массива. |
| *RedArrayLengthPtr | | число элементов в редукционной переменной-массиве. |
| LocArrayPtr | | указатель на массив с дополнительной информацией, сопровождающей редукционную операцию (число элементов в этом массиве равно числу элементов в редукционной переменной-массиве). |
| *LocElmLengthPtr | | длина в байтах одного элемента массива с дополнительной информацией. |
| *StaticSignPtr | | признак создания статической редукционной переменной. |
Функция crtred_ создает объект, описывающий редукционную переменную, и возвращает ссылку на него (или просто ссылку на редукционную переменную).
Существуют следующие номера редукционных операций (в скобках указаны именованные константы языка C):
-
сумма (rf_SUM);
-
произведение (rf_MULT);
-
максимум (rf_MAX);
-
минимум (rf_MIN);
-
поразрядное логическое "И" (rf_AND);
-
поразрядное логическое "ИЛИ" (rf_OR);
-
поразрядное сравнение (поразрядное сложение по модулю 2, rf_XOR);
-
поразрядная эквивалентность (поразрядное сложение по модулю 2 с последующим инвертированием всех разрядов, rf_EQU);
-
неравенство (rf_NE);
-
равенство (rf_EQ).
Операции с номерами 5, 6, 7 и 8 применимы только для редукционных переменных типа int или long (см. ниже).
Результат операции с номером 9 (rf_NE) имеет ненулевое значение ("ИСТИНА"), если в момент её запуска значения редукционной переменной различны хотя бы на двух процессорах, и нулевое ("ЛОЖЬ") в противном случае.
Результат операции с номером 10 (rf_EQ) имеет ненулевое значение ("ИСТИНА"), если в момент её запуска значения редукционной переменной одинаковы на всех процессорах, и нулевое ("ЛОЖЬ") в противном случае.
Дополнительная информация (или информация локализации), сопровождающая редукционную операцию, зависит от алгоритма задачи и формируется программой пользователя. Из перечисленных редукционных операций её задание имеет смысл только для операций rf_MAX и rf_MIN и превращает их в позиционные редукционные операции MAXLOC и MINLOC. Предположительно, дополнительной информацией в этих случаях являются в том или ином виде заданные координаты максимума или минимума. Система поддержки лишь обеспечит пересылку её от процессора, в котором был найден максимум или минимум, всем остальным процессорам. Отсутствие информации локализации указывается равным NULL значением указателя LocArrayPtr или нулевым значением длины элемента массива с информацией локализации.
Тип элементов редукционной переменной-массива может иметь значения (в скобках указаны именованные константы языка C):
-
int (rt_INT);
-
long (rt_LONG);
-
float (rt_FLOAT);
-
double (rt_DOUBLE).
Задаваемый ненулевым значением *StaticSignPtr признак статической редукционной переменной означает создание переменной (точнее, описывающего её объекта), не уничтожаемой при выходе из программного блока (см.п.8). Такая редукционная переменная может быть уничтожена только явно, с помощью рассмотренной ниже функции delred_ .
Замечание. Чтобы избежать предупреждений, выдаваемых Фортран-компилятором при обращении к функции crtred_ с различными типами редукционных переменных, в системе поддержки предусмотрена функция
| RedRef crtrdf_ ( | long | *RedFuncNumbPtr, |
отличающаяся от функции crtred_ вторым параметром:
| *RedArrayAddrPtr | | указатель на редукционную переменную-массив, приведенный к типу AddrType с помощью одной из функций, рассмотренных в п.17.7. |
Остальные параметры функции crtrdf_ аналогичны соответствующим параметрам функции crtred_ .
11.2Задание типа индексных переменных, значения которых определяют координаты локального максимума или минимума редукционной переменной
| long lindtp_ ( | RedRef | *RedRefPtr, |















