<= Fortran DVM - детальный дизайн (начало)

Компилятор Fortran DVM. Детальный дизайн (продолжение)
* 25 июня 2000 *


5 Детальное описание модулей компилятора

5.1 Трансляция конструкций языка Fortran DVM (модуль dvm.cpp)

Ниже представлена схема вызова функций верхнего уровня модуля dvm.cpp :

int main ( int
char
argc,
*argv[] );

Функция обрабатывает параметры компиляции и устанавливает режимы компиляции. Она инициализирует структуры данных компилятора, реструктурирует дерево разбора в соответствии с режимами компиляции, вызывая для этого функцию TranslateFileDVM( ), и генерирует новый код на Фортране 77 по реструктурированному внутреннему представлению с помощью функции unparse( ) класса SgFile. Функция возвращает 1, если в программе обнаружены ошибки.

void TranslateFileDVM ( SgFile *f )

f - указатель на программный файл

Если требуется сгенерировать параллельную программу (опция –p), тогда вызывается функция TransFunc( ) , иначе вызывается функция InsertDebugStat( ).

void TransFunc ( SgStatement *func )

func - указатель на заголовок процедуры

Сканирует операторы процедуры в лексическом порядке, пока не встретится последний оператор процедуры.

Обработка операторов и директив спецификации.

Директивы DISTRIBUTE включаются в список. Строятся деревья выравнивания, когда обрабатываются директивы ALIGN.

При сканировании операторов и директив спецификации, генерируются обращения к функциям системы поддержки Lib-DVM для создания распределенных массивов, которые вставляются в процедуру перед первым исполняемым оператором. Функция GenDistArray( ) создает распределенный массив (объект Lib-DVM ) для массива с атрибутом DISTRIBUTE, а также для всех массивов, непосредственно или косвенно выровненных на него.

Обработка исполняемых операторов и директив.

Все ссылки на элементы распределенных массивов в операторах присваивания, CALL , арифметический IF, логический IF, IF-THEN, ELSE_IF и вычисляемый GOTO линеаризуются.

Директива DVM заменяется последовательностью вызовов функций системы поддержки Lib-DVM. Когда новый оператор вставляется в программу, выполняется, если это необходимо, реструктурирование графа управления (перемещение или замена меток, замена оператора логический IF конструкцией IF...THEN...ENDIF и т.п.). Функции ReplaceContext( ), doAssignStmtAfter( ), InsertNewStatementAfter( ), InserNewStatementBefore( ) предназначены для включения новых операторов в дерево разбора и его реструктурирования.

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

Список вызываемых функций:

TempVarDVM ChangeDistArrayRef
DeclareVarDVM ChangeDistArrayRef_Left
RTLInit DebugVarArrayRef
RTLExit DebugVarArrayRef_Left
BeginBlock ChangeArg_DistArrayRef
EndBlock DebugArg_VarArrayRef
GetAM ReplaceAssignByIf
GetVM ReplaceContext
doDisRuleArrays ParallelLoop
GenDistArray AddToGroupNameList
GenAlignArray AllocateArray
AlignTree AssignPointer
InsertNewStatementBefore CreateBoundGroup
InsertNewStatementAfter ShadowList
doAssignStmt Calculate
doAssignStmtAfter hasNewValueClause
doAssignTo_After StartBound
Extract_Stmt WaitBound
ContinueWithLabel SendBoun
RemoteAccessEnd CreateReductionGroup
GoRoundEntry ReductionList
BeginBLockForEntry StartRed
initMask WaitRed
ReplaceDoLabel ReductionVarsStart
Error doAlignRule
err RealignArray
addToStmtList RealignArr
ReplaceDoNestLabel_Above DistObjectRef
CloseDoInParLoop RedistributeArray
CloseParLoop control_list_open
EndParLoop ReplaceByIfStmt
EndPl InsertSendIOSTAT
isDoEndStmt InsertSendInquire
CloseLoop InsertSendInputList
DebugLoop IOcontrol
SeqLoopBegin TestIOList
SeqLoopEndInParLoop IO_ThroughBuffer
OverLoopAnalyze D_Skpbl
SeqLoopEnd D_Lnumb
DeleteObject D_Fname
OpenInterval St_Binter
CloseInterval St_Einter
Value St_Biof
lastStmtOfDo St_Eiof
AddRemoteAccess St_Eloop
RemoteVariableList BeginDebugFragment
RankOfSection EndDebugFragment
Rank ArrayHeader
isListOfArrays TypeControl
ReconfPS CreateTaskArray
InitGroups SetDoVar
InitHeap PSReference
hasOntoClause SearchDistArrayRef
DebugTaskRegion CloseTaskRegion
StartTask isParallelLoopEndStmt
StopAM CreateBG
doIfThenConstrForPrefetch LoadBg
InitRemoteGroups IsLIFReductionOp
INDLoopBegin IsReductionOp
IEXLoopAnalyse OffDoVarsOfNest
IndependentLoop  

void InsertDebugStat ( SgStatement *func )

func - указатель на заголовок процедуры

Функция генерирует последовательную программу с вызовами функций отладчика и анализатора производительности. Процессом генерации новых операторов управляют параметры компиляции (-e… и -d…).

Операторы процедуры сканируются в лексическом порядке, пока не встретится последний оператор процедуры. Операторы и директивы спецификации пропускаются.

Если пользователь указал в командной строке не нулевой уровень отладки, операторы, включающие выражения (присваивания, CALL , арифметический IF и т.п.), окружаются вызовами функций отладчика для контроля значений переменных. Функция вставляет вызовы функций отладчика в начало и конец каждого параллельного цикла и вызовы функций анализатора производительности в начало и конец каждого интервала.

Список вызываемых функций:

TempVarDVM DebugVarArrayRef
RTLInit DebugVarArrayRef_Left
RTLExit DebugArg_VarArrayRef
InsertNewStatementBefore SkipParLoopNest
InsertNewStatementAfter ReplaceContext
doAssignStmtAfter ParallelLoop_Debug
Extract_Stmt isParallelLoopEndStmt
addToStmtList AddToGroupNameList
ReplaceDoNestLabel_Above CreateReductionGroup
CloseDoInParLoop ReductionList
CloseParLoop D_Lnumb
isDoEndStmt D_Fname
ReplaceFuncCall D_Skpbl
InitRemoteGroups D_Iter_ON
CloseLoop St_Binter
DebugLoop St_Einter
SeqLoopBegin St_Biof
SeqLoopEndInParLoop St_Eiof
OverLoopAnalyze St_Eloop
SeqLoopEnd DeclareVarDVM
OpenInterval DeleteObject
CloseInterval Error
Value err
initMask InitGroups
isLIFReductionOp IsReductionOp
IEXLoopAnalyze IndependentLoop_Debug
BeginDebugFragment SkipIndepLoopNest
EndDebugFragment DebugTaskRegion
INDReductionDebug CloseTaskRegion

void initialize ( )
Функция инициализирует переменные компилятора, используемые в отладочном режиме.

void initVariantNames ( )
Функция инициализирует таблицу признаков вершин дерева разбора.

void initLibNames ( )
Функция инициализирует таблицу имен функций системы поддержки Lib-DVM.

void initDVM ( )
Функция вставляет символы функций Lib-DVM в Таблицу символов.

void initMask ( )
Эта функция обнуляет маску использования функций Lib-DVM. Функции компилятора, генерирующие вызовы функций библиотеки Lib-DVM устанавливают соответствующий элемент маски равным 1. Операторы объявления создаются только для замаскированных (используемых в процедуре) функций Lib-DVM.

void TempVarDVM ( SgStatement *func )

func - указатель на заголовок процедуры

Функция помещает в Таблицу символов символы следующих служебных переменных:

integer dvm000(...) - массив, используемый для подготовки аргументов и
запоминания результатов функций Lib-DVM
integer hpf000(...) - массив, используемый для подготовки аргументов и
запоминания результатов функций Lib-DVM
(используется только в HPF-DVM программе)
integer i0000m(0:0) - база для адресации распределенных массивов типа
integer
real r0000m(0:0) - база для адресации распределенных массивов типа
real
double precision d0000m(0:0) - база для адресации распределенных массивов типа
double precision
logical l0000m(0:0) - база для адресации распределенных массивов типа
logical
complex c0000m(0:0) - база для адресации распределенных массивов типа
complex
integer i000io(1000) - буфер для ввода-вывода распределенных массивов
типа integer
real r000io(1000) - буфер для ввода-вывода распределенных массивов
типа real
double precision d000io(1000) - буфер для ввода-вывода распределенных массивов
типа double precision
logical l000io(1000) - буфер для ввода-вывода распределенных массивов
типа logical
complex c000io(1000) - буфер для ввода-вывода распределенных массивов
типа complex
integer idvm00 - do-переменные для реализации ввода-вывода
  idvm01 распределенных массивов
  . . .  
  idvm07  
integer i000bf(...) - буфер удаленных данных типа integer
real r000bf(...) - буфер удаленных данных типа real
double precision d000bf(1000) - буфер удаленных данных типа double precision
logical l000bf(1000) - буфер удаленных данных типа logical
complex c000bf(1000) - буфер удаленных данных типа complex

void DeclareVarDVM ( SgStatement *lstat )

lstat - указатель на оператор

Создает операторы объявления служебных переменных, используемых в процедуре:

и вставляет их в процедуру вслед за оператором lstat (последним оператором спецификации или оператором, предшествующем DATA ).
(См. TempVarDVM( )).

5.1.1 Создание распределенного массива и его перераспределение

void GenDistArray ( SgSymbol
int
SgExpression
SgStatement
*das,
idisars,
*ps
*stdis );
       
das - указатель на символ распределенного массива
idisars - правила отображения (форматы распределения) хранятся в элементах служебного массива dvm000 : dvm000(idisars), dvm000(idisars+1),...
ps - указатель на выражение, являющееся ссылкой на массив
процессоров
stdis - указатель на оператор DISTRIBUTE

Генерирует операторы для создания объекта системы Lib-DVM и размещения в памяти массива, объявленного с атрибутом DISTRIBUTE, а также всех массивов, непосредственно или косвенно выровненных на него, и вставляет эти операторы перед первым исполняемым оператором процедуры.

void GenAlignArray ( align
align
int
int
*node,
*root,
nr
iaxis );
       
node - указатель на вершину дерева выравнивания, которая
соответствует массиву с атрибутом ALIGN
root - указатель на вершину дерева выравнивания, на который
выравнивается массив node
nr - число правил выравнивания
iaxis - правила выравнивания (AxisArray(nr), CoefArray(nr), ConstArray(nr)) хранятся в элементах служебного массива
dvm000 : dvm000(iaxis), dvm000(iaxis+1),...

Генерирует операторы для создания объекта системы Lib-DVM и отведения памяти для массива с атрибутом ALIGN и вставляет эти операторы перед первым исполняемым оператором процедуры.

void doAlignRule_1 ( int rank )

rank - размерность массива

Генерирует операторы для инициализации 3 массивов правил выравнивания:

AxisArray(i) = 1
CoeffArray(i) = 1
ConstArray(i) = 1 , i=1, rank

которые используются как аргументы функции align( ) системы поддержки Lib-DVM.

int doAlignRule ( SgSymbol
SgStatement
int
*alignee,
*algn_st,
iaxis );
       
alignee - указатель на символ выравниваемого массива
algn_st - указатель на оператор ALIGN
iaxis - индекс элемента служебного массива dvm000 , в котором
хранится AxisArray(1)

Функция генерирует операторы для создания массивов правил выравнивания, которые используются в качестве аргументов функции align( ) системы поддержки Lib-DVM.

Функция возвращает число правил выравнивания (длину списка align-source-list в директиве ALIGN).

void AlignTree ( align *root )

root - указатель на корень дерева выравнивания

Осуществляет просмотр дерева выравнивания, создает распределенный массив для каждой вершины дерева, вызывая функцию GenAlignArray().

int doDisRuleArrays ( SgExpression
SgExpression
*dist_format,
*aster );
       
dist_format - список форматов распределения
aster - указатель на выражение * или нулевой указатель

Функция генерирует операторы для создания 2 массивов правил отображения, которые используются как аргументы (AxisArray, DistrParamArray) функций distr( ) и redis( ) системы поддержки Lib-DVM.

Функция возвращает индекс элемента массива dvm000 , хранящего первое правило отображения (AxisArray(1)).

void RedistributeArray ( SgSymbol
int
SgExpression
int
SgExpression
SgStatement
*das,
idisars,
*ps
sign
*dasref
*stdis );
       
das - указатель на символ перераспределяемого массива
idisars - правила отображения (форматы распределения) хранятся в элементах служебного массива dvm000 : dvm000(idisars), dvm000(idisars+1),...
ps - указатель на выражение, являющееся ссылкой на массив процессоров
sign - признак, определяющий надо ли обновлять значения элементов перераспределяемого массива
dasref - указатель на выражение, являющееся ссылкой на перераспределяемый массив
stdis - указатель на директиву REDISTRIBUTE

Генерирует оператор для перераспределения массива:

dvm000(i) = redis(...)

и вставляет его в процедуру вместо директивы REDISTRIBUTE.

Для массива, объявленного директивой ALIGN или DISTRIBUTE в форме

*DVM$ DISTRIBUTE  :: …

генерируется последовательность операторов для создания распределенного массива.

void RealignArray ( SgSymbol
SgSymbol
int
int
int
SgStatement
*als,
*tgs,
iaxis
nr
new_sign,
*stal );
       
als - указатель на символ массива, который выравнивается заново
tgs - указатель на символ массива, на который выравнивается als
iaxis - правила выравнивания хранятся в элементах служебного массива dvm000 : dvm000(iaxis), dvm000(iaxis+1),...
nr - число правил выравнивания
new_sign - признак, определяющий надо ли обновлять значения элементов перераспределяемого массива
stal - указатель на директиву REALIGN

Генерирует оператор, для того чтобы заново выровнять массив:

dvm000(i) = realn(...)

и вставляет его в процедуру вместо директивы REALIGN.

void AllocateArray ( SgStatement
distribute_list
*stmt,
*distr );
       
stmt - указатель на оператор с вызовом функции ALLOCATE
distribute_list - список директив DISTRIBUTE

Анализируется POINTER-переменная в левой части оператора присваивания stmt. Если она имеет атрибут DISTRIBUTE, тогда вызывается функция AllocDistArray( ), иначе вызывается функция AllocAlignArray( ).

void AllocateDistArray ( SgSymbol
SgExpression
SgStatement
SgStatement
*p,
*desc,
*stdis
*stmt );
       
p - указатель на символ POINTER-переменной
desc - указатель на дескриптор (дескриптор – вектор размеров измерений динамического массива)
stdis - указатель на директиву DISTRIBUTE, специфицирующую p
stmt - указатель на оператор с вызовом функции ALLOCATE:
p = ALLOCATE(desc,...)

Генерирует операторы для создания объекта системы Lib-DVM и отведения памяти для динамического массива с атрибутом DISTRIBUTE, а также для всех массивов, непосредственно или косвенно выровненных на него, и вставляет эти операторы вместо оператора stmt.

void AllocateAlignArray( SgSymbol
SgExpression
SgStatement
*p,
*desc,
*stmt );
       
p - указатель на символ POINTER-переменной
desc - указатель на дескриптор (дескриптор – вектор размеров измерений динамического массива)
stmt - указатель на оператор с вызовом функции ALLOCATE:
p = ALLOCATE(desc,...)

Генерирует операторы для создания объекта системы Lib-DVM и отведения памяти для массива, объявленного с атрибутами ALIGN и POINTER, а также для всех массивов, выровненных на него, и вставляет эти операторы в процедуру вместо оператора stmt.

Вызываются функции AlignTreeAlloc( ) и AlignAllocArray( ).

void AlignTreeAlloc ( align *root )

root - указатель на корень дерева выравнивания

Осуществляет просмотр дерева выравнивания, создает распределенный массив для каждой вершины дерева, которая соответствует массиву без атрибута POINTER, вызывая функцию AlignAllocArray() .

void AlignAllocArray( align
align
int
int
SgExpression
*node,
*root,
nr
iaxis
*desc );
       
node - указатель на вершину дерева выравнивания, соответствующую выравниваемому массиву с атрибутом POINTER
root - указатель на вершину дерева выравнивания, соответствующую массиву, на который выравнивается node
nr - число правил выравнивания
iaxis - правила выравнивания (AxisArray(nr), CoefArray(nr), ConstArray(nr)) хранятся в элементах служебного массива
dvm000 : dvm000(iaxis), dvm000(iaxis+1),...
desc - указатель на дескриптор (дескриптор – вектор размеров измерений динамического массива)

Генерирует операторы для создания объекта системы Lib-DVM и отведения памяти для динамического массива с атрибутом ALIGN и вставляет эти операторы в процедуру вместо оператора: pointer = ALLOCATE(desc,...).

void ArrayHeader ( SgSymbol
int
*ar,
ind );
       
ar - указатель на символ массива
ind - 0, если ar имеет атрибут POINTER
1, если
ar – распределенный массив
n, где dvm000(n) – элемент служебного массива, хранящий
указатель на представление абстрактной машины, если ar - TEMPLATE
-1, если
ar объявлен как массив с отложенным распределением

Добавляет атрибут ARRAY_HEADER к символу распределенного объекта ar (indзначение атрибута).

5.1.2 Ссылки на распределенные массивы

void DistArrayRef ( SgExpression
int
SgStatement
*e,
modified
*st );
       
e - указатель на выражение, являющееся ссылкой на массив
modified - признак, определяющий в правой или левой части оператора присваивания находится ссылка на массив e
st - указатель на оператор, где встретилась ссылка e

Линеаризует ссылку на элемент распределенного массива в правой части оператора присваивания, т.е. заменяет ссылку

A(I1,I2, ..., IN)

выражением

где:

A - имя распределенного массива
base - i0000m , если A имеет тип integer
    r0000m , если A имеет тип real
    d0000m , если A имеет тип double precision
    c0000m , если A имеет тип complex
    l0000m , если A имеет тип logical

 

SgExpression *LinearForm ( SgSymbol
SgExpression
*ar,
*el );
ar - указатель на символ распределенного массива
el - указатель на список индексов (I1,I2, ..., IN) ссылки на массив

Генерирует выражение

где A - имя распределенного массива.

void ChangeDistArrayRef ( SgExpression *e )

e - указатель на выражение

Просматривает выражение e и линеаризует каждую ссылку на элемент распределенного массива (вызывает DistArrayRef( )).

void ChangeDistArrayRef_Left ( SgExpression *e )

e - указатель на выражение

Просматривает выражение e в левой части оператора присваивания и линеаризует ссылку на элемент распределенного массива (вызывает DistArrayRef( )).

void ChangeArg_DistArrayRef ( SgExpression *ele )

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

Просматривает выражение ele и линеаризует ссылки на распределенные массивы, за исключением ссылок на весь массив.

void DebugVarArrayRef( SgExpression
SgStatement
*e,
*stmt );
       
e - указатель на выражение
stmt - указатель на оператор, содержащий выражение e

Функция просматривает выражение e и линеаризует каждую ссылку на элемент распределенного массива (вызывает DistArrayRef( )). Если задан режим отладки, эта функция вставляет перед оператором stmt операторы для проверки значений переменных во время выполнения программы в отладочном режиме.

void DebugVarArrayRef_Left ( SgExpression
SgStatement
SgStatement
*e,
*stmt
*stcur );
       
e - указатель на выражение в левой части оператора присваивания
stmt - указатель на оператор, содержащий выражение e
stcur - указатель на оператор, вслед за котором новые операторы должны быть вставлены

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

void DebugArg_VarArrayRef ( SgExpression
SgStatement
*ele,
*stmt );
       
ele - указатель на выражение, которое является фактическим аргументом процедуры
stmt - указатель на оператор, содержащий выражение e

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

5.1.3 Параллельный цикл

void ParallelLoop ( SgStatement *stmt )

stmt - указатель на директиву 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 ]
* отображение параллельного цикла              (1)
      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 ]

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

label CONTINUE

генерируются функцией TransFunc( ) во время обработки данного оператора.

Если задан режим отладки, создаются операторы CALL:

call dbegpl(...)
call  diter(...)
call  dendl(...)

которые вставляются в блок (1) перед оператором IF, перед первым оператором тела параллельного цикла и после оператора

go to lab1

соответственно.

Если задан режим анализа производительности, создаются операторы CALL:

call bploop(...)
call  eloop(...)

которые вставляются перед первым и вслед за последним операторами блока (1).

Для генерации блоков реализации спецификаций ACROSS, SHADOW_RENEW, REDUCTION и REMOTE_ACCESS, вызываются следующие функции:

DepList
ShadowList
doIfForReduction
ReductionList
RemoteVariableList

void ParallelLoop_Debug ( SgStatement *stmt )

stmt - указатель на директиву PARALLEL

Если задан режим отладки, создаются операторы CALL:

call dbegpl(...)
call  diter(...)

, которые вставляются перед гнездом операторов DO и перед первым оператором тела параллельного цикла, соответственно. Эта функция генерирует блоки операторов REDUCTION-block-1 и REDUCTION-block-2, если необходимо.

Если задан режим анализа производительности, создаются операторы CALL:

call bploop(...)
call  eloop(...)

, которые вставляются, соответственно, перед и после гнезда циклов DO.

void ReductionList ( SgExpression
SgExpression
SgStatement
SgStatement
SgStatement
*el,
*gref
*st
*stmt1
*stmt2 );
       
el - список редукций
gref - указатель на выражение, являющееся ссылкой на группу редукций
st - указатель на директиву PARALLEL со спецификацией REDUCTION, содержащей список редукций el
stmt1 - указатель на оператор, вслед за которым вставляются новые операторы
stmt2 - указатель на оператор, вслед за которым вставляются новые операторы

Для каждой редукции в списке el, функция генерирует и вставляет в процедуру следующие операторы:

* создание редукционной переменной
      dvm000(irv) = crtrgf(reduction-function, red-var,…)
* включение редукционной переменной в группу
      dvm000(i) = insred(gref,dvm000(irv),…)

Первый оператор вставляется вслед за оператором stmt1 , а второй – вслед за stmt2.

void ShadowList ( SgExpression
SgStatement
SgExpression
*el,
*st
*gref );
       
el - список renewee-list
st - указатель на директиву PARALLEL со спецификацией SHADOW_RENEW или директиву SHADOW_GROUP, содержащую список el
gref - указатель на выражение, являющееся ссылкой на группу

Для каждого массива в списке el, генерируется и вставляется в процедуру следующий оператор:

* включение теневой грани в группу
      dvm000(i) = inssh(gref,array,...)
void RemoteVariableList ( SgSymbol
SgExpression
SgStatement
*group
*rml,
*stmt );
       
group - указатель на символ группы
rml - список ссылок на массивы
stmt - указатель на директиву PARALLEL со спецификацией REMOTE_ACCESS или директиву REMOTE_ACCESS, содержащую список rml

Функция генерирует и вставляет в процедуру операторы для чтения удаленных данных в буфер (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

5.2 Трансляция операторов ввода-вывода (модуль io.cpp)

Модуль компилятора io.cpp включает функции для трансляции операторов ввода-вывода.

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

int TestIOList ( SgExpression
SgStatement
*iol,
*stmt );
       
iol - список ввода-вывода
stmt - указатель на оператор ввода-вывода

Функция анализирует список ввода-вывода. Она возвращает 1, если в списке присутствуют ссылки на распределенные массивы, или 0, в противном случае.

Вызывает функции ImplicitLoopTest( ) , IOitemTest( ).

int ImplicitLoopTest( SgExpression
SgStatement
*eim,
*stmt );
       
eim - указатель на неявный цикл
stmt - указатель на оператор ввода-вывода

Функция анализирует список элементов неявного цикла. Если в списке нет ссылок на распределенные массивы, функция возвращает 1, в противном случае – 0.

int IOitemTest ( SgExpression
SgStatement
*e,
*stmt );
       
e - указатель на элемент списка ввода-вывода
stmt - указатель на оператор ввода-вывода

Функция возвращает 1, если элемент списка ввода-вывода не является ссылкой на распределенный массив, или 0, в противном случае.

int IOcontrol ( SgExpression
SgExpression
int
*e,
*ioc[]
type );
       
e - список управляющей информации
ioc - массив управляющих параметров ввода-вывода
type - тэг признака оператора ввода-вывода (PRINT_STAT, WRITE_STAT, READ_STAT)

Функция анализирует список управляющей информации оператора передачи данных и присваивает элементам массива ioc[] значения управляющих параметров (UNIT, FMT, ERR и т.п.). Если обнаруживаются синтаксические ошибки, функция возвращает 0, иначе – 1.

int control_list1 ( SgExpression
SgExpression
*e,
*ioc[] );
       
e - список управляющей информации
ioc - массив управляющих параметров ввода-вывода

Функция анализирует список управляющей информации операторов BACKSPACE, REWIND и ENDFILE и присваивает элементам массива ioc[] значения управляющих параметров (UNIT, ERR и т.п.). Если обнаруживаются синтаксические ошибки, функция возвращает 0, иначе – 1.

int control_list_open ( SgExpression
SgExpression
*e,
*ioc[] );
       
e - список управляющей информации
ioc - массив управляющих параметров ввода-вывода

Функция анализирует список управляющей информации операторов OPEN, CLOSE, INQUIRE и присваивает элементам массива ioc[] значения управляющих параметров (UNIT, ERR и т.п.). Если обнаруживаются синтаксические ошибки, функция возвращает 0, иначе – 1.

void IO_ThroughBuffer( SgSymbol
SgStatement
*ar,
*stmt );
       
e - указатель на символ распределенного массива
stmt - указатель на оператор ввода-вывода

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

Пусть A(N1,N2,...,Nk) – ссылка на распределенный массив размерности k, BUF(L) – вектор того же типа, что и массив A. Тогда компилятор заменит оператор ввода-вывода последовательностью операторов по следующей схеме:

ввод:

IF(tstio( ) .ne. 0 ) READ (...) (BUF(j), j = 1, N1 * ...*Nn * m)
  n >= 1
копирование-секции-массива (BUF(1 : N1 * ...*Nn * m),
  n >= 1
  A(1: N1,...,1:Nn , In+1 +1: In+1 +m , In+2 +1, ..., Ik +1) )
    n >= 1   n+1 <= k   n+2 <= k  

вывод:

копирование-секции-массива (BUF(1 : N1 * ...*Nn * m),
  n >= 1
  A(1: N1,...,1:Nn , In+1 +1: In+1 +m , In+2 +1, ..., Ik +1) )
    n >= 1   n+1 <= k   n+2 <= k  
IF(tstio( ) .ne. 0 ) WRITE (...) (BUF(j), j = 1, N1 * ...*Nn * m)
  n >= 1

label CONTINUE

Операция копирования-секции-массива реализуется с помощью функции системы поддержки arrcpy( ).

5.3 Реструктурирование дерева разбора (модуль stmt.cpp)

Модуль stmt.cpp составляют функции реструктурирования дерева разбора.

void InsertNewStatementAfter( SgStatement
SgStatement
SgStatement
*stat,
*current
*cp );
       
stat - указатель на вставляемый оператор
current - указатель на оператор, вслед за которым вставляется оператор stat
cp - указатель на родительский оператор для stat

Оператор stat вставляется в дерево разбора (программу) вслед за оператором current, так что его родителем по управлению является оператор cp.

void InsertNewStatementBefore( SgStatement
SgStatement
*stat,
*current );
       
stat - указатель на вставляемый оператор
current - указатель на оператор, перед которым вставляется оператор stat

Оператор stat вставляется в дерево разбора (программу) перед оператором current.

void doAssignStmt ( SgExpression *re )

re - указатель на выражение для правой части оператора присваивания

Создает оператор присваивания с правой частью re :

dvm000(i) = re

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

SgExpression *LeftPart_AssignStmt ( SgExpression *re )

re - указатель на выражение для правой части оператора присваивания

Создает оператор присваивания с правой частью re :

dvm000(i) = re

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

void doAssignTo ( SgExpression
SgExpression
*le,
*re );
       
le - указатель на выражение для левой части оператора присваивания
re - указатель на выражение для правой части оператора присваивания

Создает оператор присваивания:

le = re

и вставляет его перед оператором where (глобальная переменная).

void doAssignTo_After ( SgExpression
SgExpression
*le,
*re );
       
le - указатель на выражение для левой части оператора присваивания
re - указатель на выражение для правой части оператора присваивания

Создает оператор присваивания:

le = re

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

void doAssignStmtAfter( SgExpression *re );
       
re - указатель на выражение для правой части оператора присваивания

Создает оператор присваивания с правой частью re :

dvm000(i) = re

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

void doAssignStmtBefore( SgExpression
SgStatement
*re,
*current );
       
re - указатель на выражение для правой части оператора присваивания
current - указатель на оператор

Создает оператор присваивания с правой частью re :

dvm000(i) = re

и вставляет его перед оператором current.

void Extract_Stmt ( SgStatement *st )

st - указатель на оператор

Удаляет оператор st из дерева разбора.

void ReplaceByIfStmt ( SgStatement *st )

st - указатель на оператор

Заменяет оператор st оператором IF:

IF (tstio( ) .NE. 0) st

void ReplaceDoNestLabel( SgStatement
SgLabel
*last_st,
*new_lab );
       
last_st - указатель на оператор, завершающий гнездо операторов DO
new_lab - указатель на новую метку

Заменяет метку в гнезде операторов DO, которое заканчивается оператором last_st, меткой new_lab и вставляет оператор CONTINUE.

       DO 1 I1 = 1,N1                  DO   new_lab   I1 = 1,N1
       DO 1 I2 = 1,N2                  DO   new_lab   I2 = 1,N2
          .   .   .            ==>           .   .   .       
       DO 1 Ik = 1,Nk                  DO   new_lab   Ik = 1,Nk
          .   .   .                         .   .   . 
 1     last-statement            1     last-statement   
                               new_lab CONTINUE
void ReplaceDoNestLabel_Above ( SgStatement
SgStatement
SgLabel
*last_st,
*from_st,
*new_lab );
       
last_st - указатель на оператор, завершающий гнездо операторов DO
from_st - указатель на оператор
new_lab - указатель на новую метку

Заменяет метку тех операторов DO, которые располагаются перед оператором from_st и заканчиваются оператором last_st, меткой new_lab и вставляет оператор CONTINUE.

    DO 1 I1 = 1,N1                            DO  new_lab  I1 = 1,N1
        .  .   .                                  .   .   .       
      DO 1 Ik = 1,Nk                            DO  new_lab  Ik = 1,Nk
CDVM$ PARALLEL (J1,...,Jm) ON ...  ==>     CDVM$ PARALLEL (J1,...,Jm) ON ...
      DO 1  J1 = 1,N1                           DO 1  J1 = 1,N1
        .   .   .                                 .   .   .          
      DO 1  Jm = 1,Nm                           DO 1  Jm = 1,Nm
        .   .   .                                 .   .   . 
1     last_statement                      1     last_statement
                                        new_lab CONTINUE
void ReplaceDoLabel ( SgStatement
SgLabel
*last_st,
*new_lab );
       
last_st - указатель на последний оператор конструкции DO
new_lab - указатель на новую метку

Заменяет метку оператора DO меткой new_lab и вставляет оператор CONTINUE.

      DO  1  I = 1,N                    DO  new_lab  I = 1,N
          .   .   .       ==>                .   .   . 
1     last-statement              1     last-statement   
                                new_lab CONTINUE

void ReplaceContext ( SgStatement *stmt )

stmt - указатель на оператор

Если оператор stmt или содержащий его оператор логический IF является последним оператором тела DO-цикла, то меняется метка гнезда циклов и вставляется оператор CONTINUE (ReplaceDoNestLabel(stmt)). Если родитель по управлению для оператора stmt является оператором логический IF, тогда он заменяется конструкцией IF_THEN.

void LogIf_to_IfThen ( SgStatement *stmt )

stmt - указатель на оператор

Заменяет оператор логический IF:

IF ( условие ) stmt

конструкцией:

IF ( условие ) THEN
stmt
ENDIF

SgStatement *doIfThenConstr ( SgSymbol *ar )

ar - указатель на символ массива

Создает конструкцию:

IF ( ar(1) .EQ. 0) THEN
ENDIF

и возвращает указатель на оператор IF.

int isDoEndStmt ( SgStatement *stmt )

stmt - указатель на оператор

Если оператор stmt является последним оператором тела цикла DO, то функция возвращает 1, иначе 0.

SgStatement *lastStmtOfDo ( SgStatement *stdo )

stdo - указатель на оператор DO

Возвращает указатель на последний оператор тела цикла DO.

int isParallelLoopEndStmt ( SgStatement *stmt )

stmt - указатель на оператор

Если оператор stmt является последним оператором параллельного цикла, то функция возвращает 1, иначе 0.

5.4 Трансляция конструкций языка HPF-DVM (модуль hpf.cpp)

Модуль hpf.cpp предназначен для трансляции конструкций языка HPF-DVM.

5.4.1 Обработка ссылок на распределенные массивы в HPF-DVM

int SearchDistArrayRef ( SgExpression
SgStatement
*e,
*stmt );
       
e - указатель на выражение
stmt - указатель на оператор, содержащий выражение e

Эта функция производит поиск ссылок на распределенные массивы в выражении e, добавляет к найденной ссылке атрибут REMOTE_VARIABLE, генерирует операторы для загрузки значения элемента распределенного массива в буфер и вставляет его перед оператором stmt (вызывает BufferDistArrayRef( )).

Возвращает значение 1, если обнаружена хотя бы одна ссылка, в противном случае возвращает 0.

Вызывается из функции TransFunc( ), когда обрабатывается исполняемый оператор вне тела цикла INDEPENDENT.

void BufferDistArrayRef ( SgExpression
SgStatement
*e,
*stmt );
       
e - указатель на выражение, являющееся ссылкой на элемент распределенного массива
stmt - указатель на оператор, содержащий выражение e

Генерирует оператор для загрузки в буфер значения элемента распределенного массива и вставляет его непосредственно перед оператором stmt, добавляет выражению e атрибут REMOTE_VARIABLE.

SgExpression *IND_ModifiedDistArrayRef( SgExpression
SgStatement
*e,
*st );
       
e - указатель на выражение, являющееся ссылкой на элемент
распределенного массива
st - указатель на оператор, содержащий выражение e

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

Эта функция вызывается DistArrayRef( ), когда обрабатывается оператор присваивания в теле цикла INDEPENDENT.

void *IND_UsedDistArrayRef( SgExpression
SgStatement
*e,
*st );
       
e - указатель на выражение, являющееся ссылкой на элемент распределенного массива
st - указатель на оператор, содержащий выражение e

Функция определяет вид ссылки и включает ее в список (IND_refs), который обрабатывается функцией RemoteVariableListIND( ). Вызывает функцию IND_DistArrayRef( ) для линеаризации ссылки.

Эта функция вызывается из DistArrayRef( ) во время обработки исполняемого оператора в теле цикла INDEPENDENT.

void *IND_DistArrayRef( SgExpression
SgStatement
IND_ref_list
*e,
*st
*el );
       
e - указатель на выражение, являющееся ссылкой на элемент распределенного массива
st - указатель на оператор присваивания, содержащий выражение e
el - указатель на элемент списка ссылок

Линеаризует ссылку на элемент распределенного массива в правой части оператора присваивания, т.е. заменяет ссылку

A(I1,I2, ..., IN)

ссылкой

где:

HeaderCopy - массив коэффициентов для адресации элемента распределенного массива, которые вычисляются как линейная функция элементов заголовка массива
base - i0000m , если A имеет тип integer
r0000m , если A имеет тип real
d0000m , если A имеет тип double precision
c0000m , если A имеет тип complex
l0000m , если A имеет тип logical

5.4.2 Цикл INDEPENDENT

void IndependentLoop ( SgStatement *stmt )

stmt - указатель на директиву INDEPENDENT

Тесно-гнездовой цикл INDEPENDENT:

*HPF$ INDEPENDENT
      DO  label   I1 = ...
        .   .   .
*HPF$ INDEPENDENT
      DO  label   In = ...
         тело-цикла
label CONTINUE 

транслируется в:

* создание параллельного цикла
      ipl = crtpl(n)
* отображение параллельного цикла
      it = mappl(ipl,...)
      [ inquiry-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)

Функция генерирует и вставляет в процедуру те операторы, которые предшествуют гнезду циклов DO, за исключением блока inquiry-block. Кроме того, заменяются начальное значение, конечное значение и шаг do-переменных гнезда циклов DO. Операторы, следующие за последним оператором параллельного цикла генерируются функцией TransFunc( ) в момент его обработки. Блок inquiry-block формируется функцией RemoteVariableListIND( ).

Если задан отладочный режим компиляции, то генерируются операторы CALL :

call dbegpl(...)
call  diter(...)
call  dendl(...)

которые вставляются в блок (2) перед оператором IF, перед первым оператором тела параллельного цикла и вслед за оператором

go to lab1

соответственно.

Если задан режим компиляции для анализа производительности, то генерируются операторы CALL:

call bploop(...)
call  eloop(...)

которые вставляются перед первым и вслед за последним оператором блока (2).

void IndependentLoop_Debug ( SgStatement *stmt )

stmt - указатель на директиву INDEPENDENT

Если задан отладочный режим компиляции, то генерируются операторы CALL :

call dbegpl(...)
call  diter(...)

которые вставляются перед гнездом циклов DO и перед первым оператором тела параллельного цикла, соответственно.

Если задан режим компиляции для анализа производительности, то генерируются операторы CALL:

call bploop(...)
call  eloop(...)

которые вставляются перед и после гнезда циклов.

void RemoteVariableListIND ( )

Если в правых частях операторов присваивания в теле цикла INDEPENDENT встречаются ссылки на элементы распределенных массивов, то генерируется следующий блок операторов:

      ishg = 0
      ibg  = 0
{
* запрос о типе доступа к элементам распределенного массива
      kind = rmkind(array-header,buffer-header,…,
     *                              low-shadow-array,high-shadow-array) 
      IF (kind .EQ. 4) THEN
         IF (ishg .EQ. 0) THEN
*        создание группы буферов удаленных данных 
             ibg = crtbg(0,1)
         ENDIF
*        включение буферного массива в группу RMG
         it = insrb(ibg, buffer-header)
*        вычисление коэффициентов адресации элементов буферного массива
*        NB – размерность буферного массива
         header-copy(1)   = buffer-header(2)
                      .   .   .
         header-copy(NB-1) = buffer-header(NB)
         header-copy(NB)   = 1
         header-copy(NB+1) = buffer-header(NB+1)- 
     *                      buffer-header(NB)*buffer-header(NB+3) - 
     *                      buffer-header(3)*buffer-header(2*NB+2)
         ELSE
            IF (kind .NE. 1) THEN
               IF (ishg .EQ. 0) THEN
*              создание группы теневых граней 
                  ishg = crtshg(0)
               ENDIF
*              включение теневой грани в группу
*              (с угловыми элементами или без)
               IF (kind .EQ. 2) THEN
                  it = inssh(ishg,array-header,low-shadow-array,
     *                                         high-shadow-array,0)
               ELSE
                  it = inssh(ishg,array-header,low-shadow-array,
     *                                         high-shadow-array,1)
            ENDIF
*        вычисление коэффициентов адресации элементов массива
         header-copy(1)   = f1(array-header,IkN)
                      .   .   .
         header-copy(NB)   = f1(array-header,Ik1)
         header-copy(NB+1) = f2(buffer-header(2:N+1),I1,,IN)
         ENDIF
}...   для каждой удаленной ссылки внутри тела цикла
* обновление теневых граней группы ishg 
         IF (ishg .NE. 0) THEN
            it = strtsh(ishg)
            it = waitsh(ishg)
         ENDIF
* загрузка буферов группы ibg 
        IF (ibg .NE. 0) THEN
            it = loadbg(ibg,1)
            it = waitbg(ibg)
        ENDIF

Этот блок (inquiry-block) вставляется перед первым оператором DO гнезда циклов INDEPENDENT.