fdvmPDr (1158423), страница 2
Текст из файла (страница 2)
выделяется для размещения заголовка динамического массива. Соответствующей переменной POINTER присваивается значение I.
Объявление пула динамической памяти HEAP удаляется и новый оператор описания генерируется
INTEGER HEAP(S)
где S – суммарный размер заголовков всех объявленных в процедуре динамических массивов.
Отображение массивов, объявленных директивами ALIGN и DISTRIBUTE вида
*DVM$ ALIGN :: D
*DVM$ DISTRIBUTE :: E
откладывается до выполнения директив REALIGN и REDISTRIBUTE. Только оператор создания распределенного массива генерируется в начале программной единицы.
4.2.3Директива TASK
Объект, объявленный в директиве TASK является массивом задач. Директива
*DVM$ TASK TA(M)
заменяется оператором спецификации
INTEGER TA(2,M)
Кроме того, генерируется следующая последовательность операторов, которая вставляется перед первым исполняемым оператором процедуры:
* создание представления абстрактной машины
iamv = crtamv(am,1,M,...)
* запрос ссылок на элементы представления абстрактной машины
DO lab idvm00 = 1,M
lab TA(2,idvm00) = getamr(iamv,idvm00-1)
4.2.4Директивы REMOTE_GROUP и REDUCTION_GROUP
Имя, объявленное в директиве REMOTE_GROUP, является именем группы удаленных ссылок. Директива
*DVM$ REMOTE_GROUP RMG
заменяется оператором
INTEGER RMG(3)
Если в процедуре встречается директива PREFETCH, тогда следующие операторы инициализации целочисленного массива RMG генерируются и включаются в начало исполняемой части процедуры:
RMG(1) = 0
RMG(2) = 0
RMG(3) = 0
Имя, объявленное в директиве REDUCTION_GROUP, является именем группы редукций. Директива
*DVM$ REDUCTION_GROUP REDG
заменяется оператором
INTEGER REDG
Генерируется оператор присваивания нулевого значения целой переменной REDG:
REDG = 0
Он вставляется в программную единицу перед первым исполняемым оператором.
4.3Трансляция исполняемых директив и операторов
4.3.1Директива PARALLEL
Параллельный цикл:
*DVM$ PARALLEL (I1, ..., In) ON A(…)...
DO label I1 = ...
. . .
DO label In = ...
тело-цикла
label CONTINUE
транслируется в последовательность операторов:
[ ACROSS-block-1 ]
[ REDUCTION-block-1 ]
* создание параллельного цикла
ipl = crtpl(n)
[ SHADOW-RENEW-block-1 ]
[ SHADOW-START-block ]
[ SHADOW-WAIT-block ]
* отображение параллельного цикла
it = mappl(ipl,A,...)
[ SHADOW-RENEW-block-2 ]
[ REDUCTION-block-2 ]
[ REMOTE-ACCESS-block ]
* запрос о продолжении выполнения параллельного цикла
lab1 if(dopl(ipl) .eq. 0) go to lab2
DO label I1 = ...
. . .
DO label In = ...
тело-цикла
label CONTINUE
go to lab1
* завершение параллельного цикла
lab2 it = endpl(ipl)
[ ACROSS-block-2 ]
[ REDUCTION-block-3 ]
Если в директиве PARALLEL встречается спецификация REDUCTION, то генерируются блоки операторов REDUCTION‑block‑1, REDUCTION-block-2 и REDUCTION-block-3.
REDUCTION‑block‑1:
В случае синхронной спецификации REDUCTION:
* создание группы редукций
irg = crtrg(1,1)
В случае синхронной спецификации REDUCTION (с именем группы RDG):
if(RDG.EQ.0) THEN
* создание группы редукций
RDG = crtrg(1,1)
END IF
{
* создание редукционной переменной
irv = crtrdf(reduction-function, reduction-var,...)
}... для каждой редукции из списка reduction-list
REDUCTION‑block‑2:
{
* включение редукционной переменной в группу
it = insred(irg,irv,ipl,0)
}... для каждой редукции из списка reduction-list
REDUCTION‑block‑3:
* запуск выполнения группы редукций
it = strtrd(irg)
* ожидание завершения выполнения редукций группы
it = waitrd(irg)
* уничтожение редукционной группы
it = delobj(irg)
Если в директиве PARALLEL встречается спецификация SHADOW_RENEW, то включаются блоки SHADOW‑RENEW‑block‑1 и SHADOW‑RENEW-block-2:
SHADOW‑RENEW‑block‑1:
* создание группы теневых граней
ishg = crtshg(...)
{
* включение теневой грани в группу
it = inssh(ishg,array-header,...)
}... для каждого массива из списка renewee-list
* инициализация обновления теневых граней
it = strtsh(ishg)
SHADOW‑RENEW‑block‑2:
* ожидание завершения обновления теневых граней
it = waitsh(ishg)
Спецификации SHADOW_START и SHADOW_WAIT вызывают изменение порядка выполнения итераций параллельного цикла.
SHADOW‑START‑block:
it = exfrst(shadow-group-name)
Функция exfrst( ) устанавливает следующий порядок выполнения итераций:
-
Вычисляются пересылаемые элементы локальной секции распределенного массива;
-
Запускается обмен данными теневых граней, составляющих группу;
-
Вычисляется внутренняя область локальной секции массива.
SHADOW‑WAIT‑block:
it = imlast(shadow-group-name)
Функция imlast( ) устанавливает следующий порядок выполнения итераций:
-
Вычисляется внутренняя область локальной секции массива;
-
Система поддержки ожидает завершения обмена данными теневых граней;
-
Вычисляются пересылаемые элементы локальной секции распределенного массива;
Если в директиве PARALLEL есть спецификация ACROSS, генерируются блоки ACROSS‑block‑1 и ACROSS-block-2.
ACROSS‑block‑1:
* создание группы теневых граней
ishg = crtshg(0)
{
* включение теневой грани(для обратной зависимости) в группу
it = inssh(ishg,array-header,…)
}... для каждого массива из списка dependent-array-list
* инициализация обновления теневых граней
it = strtsh(ishg)
* ожидание завершения обновления теневых граней
it = waitsh(ishg)
* уничтожение группы теневых граней
it = delobj(ishg)
. . .
* создание группы теневых граней
ishg = crtshg(0)
{
* включение теневой грани(для потоковой зависимости) в группу
it = insshd(ishg,array-header,…)
}... для каждого массива из списка dependent-array-list
* инициализация приема импортируемых элементов
it = recvsh(ishg)
* ожидание завершения операции обмена
it = waitsh(ishg)
ACROSS‑block‑2:
* инициализация передачи экспортируемых элементов
it = sendsh(ishg)
* ожидание завершения операции обмена
it = waitsh(ishg)
* уничтожение группы теневых граней
it = delobj(ishg)
Блок REMOTE-ACCESS-block генерируется в том случае, если в директиве PARALLEL есть спецификация REMOTE_ACCESS.
REMOTE-ACCESS-block:
В случае синхронной спецификации REMOTE_ACCESS :
{
* создание буферного массива
it = crtrbl(array-header,buffer-header,…)
* запуск загрузки буфера
it = loadrb(buffer-header,0)
* ожидание завершения загрузки буфера
it = waitrb(buffer-header)
* корректировка коэффициента CNB адресации элементов буфера,
* где NB – размерность буфера
buffer-header(NB+2) = buffer-header(NB+1)-
* buffer-header(NB)*buffer-header(NB+3) … -
* buffer-header(3)*buffer-header(2*NB+2)
}... для каждой удаленной ссылки
В случае асинхронной спецификации REMOTE_ACCESS (с именем группы RMG) :
IF (RMG(2) .EQ. 0) THEN
{
* создание буферного массива
it = crtrbl(array-header,buffer-header,…)
* корректировка коэффициента CNB адресации элементов буфера
buffer-header(NB+2) = buffer-header(NB+1)-
* buffer-header(NB)*buffer-header(NB+3) … -
* buffer-header(3)*buffer-header(2*NB+2)
* запуск загрузки буфера
it = loadrb(buffer-header,0)
* ожидание завершения загрузки буфера
it = waitrb(buffer-header)
* включение буфера в группу RMG
it = insrb(RMG(1),buffer-header)
}... для каждой удаленной ссылки
ELSE
IF (RMG(3) .EQ. 1) THEN
* ожидание завершения загрузки всех буферов группы RMG
it = waitbg(RMG(1))
RMG(3) = 0
ENDIF
ENDIF
4.3.2Директивы PREFETCH и RESET
Директива
*DVM$ PREFETCH RMG
транслируется в следующую последовательность опреаторов:
IF (RMG(1) .EQ. 0) THEN
RMG(1) = crtbg(0,1)
RMG(2) = 0
ELSE
it = loadbg(RMG(1),1)
RMG(2) = 1
RMG(3) = 1
ENDIF
Директива
*DVM$ RESET RMG
заменяется оператором
it = delobj(RMG(1))
4.3.3Директива MAP
Директива MAP задает отображение задачи на секцию массива процессоров. Директива
*DVM$ MAP TA(J) ONTO P(l1:u1,…,lr:ur)
заменяется операторами:
* создание подсистемы процессоров
TA(2,J) = crtps(P,l,u,0)
* отображение абстрактной машины на подсистему процессоров
it = mapam(TA(2,J),TA(1,J))
где l – вектор (lr – 1, …, l1 – 1),
u – вектор (ur – 1, …, u1 – 1).
4.3.4Конструкция TASK_REGION
Конструкция TASK_REGION
*DVM$ TASK_REGION TA
*DVM$ ON TA(1)
block-1
*DVM$ END ON
. . .
*DVM$ ON TA(M)
block-M
*DVM$ END ON
*DVM$ END TASK_REGION
транслируется в
IF (runam(TA(2,1)).EQ.0) GO TO lab1
block-1
it = stopam()
lab1 CONTINUE
. . .
labM-1 IF (runam(TA(2,M)).EQ.0) GO TO labM
block-M
it = stopam()
labM CONTINUE
4.3.5Конструкция параллельного цикла по задачам
Конструкция параллельного цикла по задачам
*DVM$ TASK_REGION TA
*DVM$ PARALLEL (I) ON TA(I)
DO label I = ...
тело-цикла
label CONTINUE
*DVM$ END TASK_REGION
транслируется в следующую последовательность операторов:
DO label I = ...
IF (runam(TA(2,I)).EQ.0) GO TO label
тело-цикла
it = stopam()
label CONTINUE
4.3.6Другие директивы FDVM
Директива REDUCTION_START заменяется оператором:
* запуск выполнения редукций заданной группы
it = strtrd(reduction-group-var)
Директива REDUCTION_WAIT заменяется операторами:
* ожидание завершения выполнения редукций
it = waitrd(reduction-group-var)
* уничтожение редукционной группы
it = delobj(reduction-group-var)
Директива SHADOW_GROUP транслируется в следующий код:
* создание группы границ(теневых граней)
shadow-group-var = crtshg(...)
{
* включение теневой грани в группу
it = inssh(shadow-group-var,array-header,...)
}... для каждого массива в списке renewee-list
Директива SHADOW_START заменяется оператором:
* инициализация обновления теневых граней
it = strtsh(shadow-group-var)
Директива SHADOW_WAIT заменяется оператором:
* ожидание завершения обновления теневых граней
it = waitsh(shadow-group-var)
Директива NEW_VALUE оказывает влияние на трансляцию следующей за ней директивы (REDISTRIBUTE или REALIGN) и не влечет за собой генерацию новых операторов. Директивы REDISTRIBUTE и REALIGN реализуются функциями redis( ) и realn( ), соответственно. Флаг NewSign устанавливается равным 1 для переменных, указанных в директиве NEW_VALUE.
4.3.7Директивы отладки
Операторы отладки DEBUG и ENDDEBUG не являются исполняемыми операторами и не требуют генерации новых операторов. Они определяют фрагмент программы, о котором пользователь хочет получить информацию в процессе отладки. Эти директивы вызывают переустановку режима компиляции. Режим компиляции зависит от максимально допустимого уровня отладки заданного в директиве DEBUG и уровня отладки, указанного для данного фрагмента в командной строке (опции – d и -e).
Директива отладки TRACE ON (TRACE OFF) “включает” (“выключает”) сбор трассы выполнения программы, реализуется с помощью функции tron( )(troff( )) системы поддержки Lib-DVM.
Если пользователь задал с помощью опции –d отладочный режим компиляции, тогда в начале и в конце каждого цикла (параллельного и последовательного) компилятор вставляет обращения к функциям отладчика: dbegpl( ), dbegsl( ) и dendl( ). Кроме того, компилятор должен обеспечить трассирование обращений к данным, выполнения итераций и задач. Обращения к соответствующим функциям отладчика включаются в программу.















