Компилятор 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.