Компилятор Fortran DVM.
Детальный дизайн (продолжение) |
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.