debugDDr (1158410), страница 5
Текст из файла (страница 5)
Каждому элементу распределенного массива при его создании ставится в соответствие структура, описывающая тип обращения к данному элементу (чтение или запись) и номер последнего витка цикла или последней параллельной задачи, в где данное обращение произошло. При вхождении в параллельный цикл или область параллельных задач, все эти структуры инициализируются начальным статусом, означающим, что к элементу массива еще не было обращений. Когда элемент используется внутри параллельной конструкции, для него запоминается номер витка или задачи и тип доступа. Если один и тот же элемент модифицируется в одном витке и используется в другом, то диагностируется ошибка зависимости параллельной конструкции по данным.
Замечание. Зависимость по данным может возникать и в случае использования размноженных переменных. Если эти переменные являются редукционными, то такая зависимость не препятствует параллельному выполнению цикла, однако, она должна быть специфицирована программистом при объявлении параллельного цикла. Если программа не имеет такой спецификации, то переменная будет трактоваться как приватная, и будет выявлена ошибка некорректного использования приватной переменной.
При обращении к элементу распределенного массива внутри параллельной конструкции, для данного массива вычисляется его локальная часть, принадлежащая выполняющемуся витку цикла или задаче.
Если локальная часть не содержит используемого элемента, то диагностируется либо ошибка обращения к нелокальному элементу массива, либо ошибка выхода за пределы массива. Если элемент принадлежит теневым граням, то проверяется наличие и завершенность операции обновления теневых граней для данного массива.
Всем теневым граням распределенного массива соответствуют следующие три состояния: обновление не выполнялось, обновление началось и обновление завершено. Программа может обращаться к теневым элементам только на чтение и только после завершения их обновления.
Состояние «обновление не выполнялось» устанавливается при модификации любого экспортируемого элемента распределенного массива. Это обеспечивает контроль некорректного доступа к теневым элементам до начала выполнения следующей операции обновления теневых граней.
5.3 Контроль приватных и неизменяемых переменных
Класс обычной (не редукционной) размноженной переменной определяется при первом обращении к ней внутри параллельной конструкции. Если это обращение на чтение, то переменная считается неизменяемой. Если же первое обращение произошло для записи в переменную, то она считается приватной.
Флаг инициализации приватной переменной устанавливается при записи в нее нового значения и сбрасывается при входе и при выходе из параллельной конструкции. При чтении переменной проверяется установка данного флага.
При использовании неизменяемых переменных проверяется тип обращения к ним. При попытке модификации таких переменных диагностируется ошибка.
5.4Контроль редукционных переменных
Переменные данного класса регистрируются при включении их в группу редукционных переменных. Каждой редукционной переменной соответствуют флаг, указывающий текущее ее состояние. Возможны следующие состояния переменной, в которые она может последовательно переходить:
-
Переменная используется внутри параллельной конструкции для вычисления частичного результата. Это начальное состояние редукционной переменной.
-
Параллельная конструкция завершилась, но операция асинхронной редукции еще не стартовала.
-
Для переменной запущена операция асинхронной редукции. Установка данного флага происходит при запуске асинхронной редукции.
-
Для переменной завершена операция редукции. Это конечное состояние редукционных переменных. При переходе в это состояние переменная удаляется из таблицы переменных, и ее класс будет определен заново.
При каждом обращении к редукционной переменной проверяется ее флаг текущего состояния. Если обращение идет после выхода из параллельной конструкции, но до завершения операции асинхронной редукции, то фиксируется ошибка.
Замечание. Неверная спецификация редукционной операции (например, задание MIN вместо MAX) не обнаруживается при данном методе, но будет обнаружена при использовании метода сравнения результатов выполнения.
5.5Контроль использования буфера удаленных элементов
Буфер удаленных элементов используется для предварительной загрузки для каждого процессора требуемых ему нелокальных элементов. Для него используются все те же проверки, которые осуществляются для распределенных массивов, за исключением следующих случаев:
-
Проверка необъявленной зависимости по данным осуществляется для распределенного массива, для которого был создан буфер удаленного доступа.
-
Проверка на инициализацию элементов осуществляется как для элементов буфера (инициализация – копирование элементов из массива в буфер), так и для элементов соответствующего распределенного массива.
-
К элементам буфера разрешено обращение только на чтение.
5.6Реализация системы динамического контроля DVM-указаний
Подсистема динамического контроля включает в себя следующие компоненты:
-
Таблица переменных – предоставляет методы для накопления информации об использовании разнотипных переменных в системе, а также быстрой выборки этой информации по адресу переменной.
-
Модуль динамического контроля – осуществляет непосредственную проверку DVM-указаний. Обращение к этому модулю идет из некоторых функций системы поддержки Lib-DVM, а так же при каждом обращении к переменной или массиву. Таблица переменных используется как вспомогательный модуль, в котором накапливается и извлекается информация о переменных при динамическом контроле.
5.6.1Режим работы динамического контроля с таблицей переменных
При анализе обращений к переменным необходимо учитывать, была ли создана переменная в параллельной или последовательной ветви, и в какой ветви программы она в данный момент используется. Для этого вводится такое понятие, как уровень выполнения программы.
Последовательная ветвь, с которой начинается выполнение программы, имеет нулевой уровень. В начале выполнения каждой параллельной конструкции текущее значение уровня увеличивается на единицу. При ее завершении значение текущего уровня соответственно уменьшается на единицу. Таким образом, значение текущего уровня определяет глубину вложенности параллельных конструкций.
При обращении к какой-либо переменной, по ее адресу осуществляется поиск соответствующей записи в таблице переменных. Здесь возможны три варианта:
-
Переменная в таблице не содержится. В этом случае создается новая запись и заносится в таблицу. Для этой записи запоминается текущий уровень исполнения программы и определяется класс использования переменной в зависимости от контекста обращения к ней. Сформированная запись возвращается как результат поиска.
-
Переменная в таблице содержится, но ее уровень исполнения, содержащийся в записи, не соответствует текущему. Для этого случая также создается новая запись и заносится в таблицу со значением текущего уровня исполнения. Сформированная запись возвращается как результат поиска. В записи запоминается ссылка на описание переменной для предыдущего уровня исполнения. Класс переменной, в этом случае, определяется не только контекстом обращения к переменной, но и классом этой переменной на предыдущем уровне исполнения. При удалении записи переменной из таблицы (например, в связи с завершением параллельной конструкции), производится обновление необходимой информации для соответствующей записи предыдущего уровня.
-
Переменная в таблице содержится, и ее уровень исполнения соответствует текущему. В этом случае найденная запись возвращается как результат поиска.
Записи в таблицу переменных также заносятся и при обращении к некоторым функциям библиотеки поддержки Lib-DVM. Например, при объявлении распределенного массива или при занесении переменной в редукционную группу создаются записи в таблице с соответствующими классами использования.
При завершении каждой параллельной конструкции, из таблицы удаляются все записи, уровень исполнения которых равен уровню исполнения завершившейся конструкции. Таким образом, время жизни записей для определенного уровня определяется временем исполнения соответствующей параллельной конструкции.
5.6.2Основные функции модуля динамического контроля
Прототипы функций динамического контроля следующие:
| void dyn_Init(void) |
Функция инициализирует все структур, необходимых для работы модуля динамического контроля.
| void dyn_Done(void) |
Функция деинициализирует все структуры модуля динамического контроля и освобождает всю выделенную память. Функция также выдает диагностику о всех найденных ошибках.
| void dyn_LevelDone(void) |
Функция вызывается при завершении текущей параллельной конструкции.
| void dyn_RemoveAll(void) |
Функция удаляет все записи из таблицы переменных динамического контроля.
| VarInfo* dyn_GetVarInfo( void* pAddr ) | ||
| pAddr | – | адрес переменной. |
Функция осуществляет поиск описания переменной по ее адресу. Если переменная не зарегистрирована, то возвращается NULL.
| VarInfo *dyn_CheckVar( char *Operand, void *addr, SysHandle *Handle, byte isWrt ) | ||
| Operand | – | имя переменной; |
| addr | – | адрес переменной; |
| Handle | – | дескриптор распределенного DVM-массива. Равен NULL для все остальных типов переменных; |
| isWrt | – | тип обращения к переменной. |
Основная функция модуля динамического контроля. Осуществляет проверку всех обращений к переменным на чтение и на запись.
| VarInfo *dyn_CheckValidVar( VarInfo *Current, void *addr, SysHandle *Handle, byte isWrt ) | ||
| Current | – | указатель на текущее описание переменной по указанному адресу; |
| addr | – | адрес переменной; |
| Handle | – | дескриптор распределенного массива; |
| isWrt | – | тип обращения к переменной. |
Функция производит проверку описания переменной на соответствие текущему уровню исполнения. Если Current не соответствует текущему уровню, то создается новое описание переменной, которое возвращается как результат функции. Иначе возвращается указатель Current.
| void dyn_CheckReadOnlyVar(char* szOperand, VarInfo *pVar, byte bIsWrt, long lLineIndex) | ||
| szOperand | – | имя переменной; |
| pVar | – | указатель на описание переменной; |
| bIsWrt | – | тип обращения к переменной; |
| lLineIndex | – | абсолютный индекс элемента массива. Равен -1 для скалярных переменных. |
Функция осуществляет проверку обращений к неизменяемым переменным.
| void dyn_CheckPrivateVar(char* szOperand, VarInfo* pVar, byte bIsWrt, long lLineIndex) | ||
| szOperand | – | имя переменной; |
| pVar | – | указатель на описание переменной; |
| bIsWrt | – | тип обращения к переменной; |
| lLineIndex | – | абсолютный индекс элемента массива. Равен -1 для скалярных переменных. |
Функция осуществляет проверку обращений к приватным переменным.
| void dyn_CheckReductVar(char* szOperand, VarInfo *pVar, byte bIsWrt, long lLineIndex) | ||
| szOperand | – | имя переменной; |
| pVar | – | указатель на описание переменной; |
| bIsWrt | – | тип обращения к переменной; |
| lLineIndex | – | абсолютный индекс элемента массива. Равен -1 для скалярных переменных. |
Функция осуществляет проверку обращений к редукционным переменным.
| void dyn_CheckDisArrayVar(char* szOperand, VarInfo *pVar, byte bIsWrt, long lLineIndex) | ||
| szOperand | – | имя переменной; |
| pVar | – | указатель на описание переменной; |
| bIsWrt | – | тип обращения к переменной; |
| lLineIndex | – | абсолютный индекс элемента массива. |
Функция осуществляет проверку обращений к распределенным DVM-массивам.
| VarInfo *dyn_DefineVar( byte type, byte Stat, void *addr, SysHandle *Handle, void *Info, PFN_VARTABLE_ELEMDESTRUCTOR pfnDestructor) | ||
| type | – | класс переменной; |
| Stat | – | статическая переменная или нет (определяет время жизни переменной); |
| addr | – | адрес переменной; |
| Handle | – | дескриптор распределенного DVM-массива. Равен NULL для всех остальных типов переменных; |
| Info | – | дополнительная информация о переменной; |
| pfnDestructor | – | деструктор переменной. Вызывается при ее удалении из таблицы переменных. |
Общая функция регистрации новой переменной.
| VarInfo *dyn_DefineReduct( byte Stat, void *addr ) | ||
| Stat | – | статическая переменная или нет (определяет время жизни переменной); |
| addr | – | адрес переменной. |
Функция регистрации редукционной переменной.
| VarInfo *dyn_DefineDisArray( SysHandle *Handle, byte Stat, DISARR_INFO *Info ) | ||
| Handle | – | дескриптор распределенного DVM-массива; |
| Stat | – | статическая переменная или нет (определяет время жизни переменной); |
| Info | – | дополнительное описание распределенного массива. |
Функция регистрации распределенного массива.
| VarInfo *dyn_DefinePrivate( void *addr, byte Stat ) | ||
| addr | – | адрес переменной; |
| Stat | – | статическая переменная или нет (определяет время жизни переменной); |
Функция регистрации переменной приватного класса.
| VarInfo *dyn_DefineReadOnly( void *addr, void *Info ) | ||
| addr | – | адрес переменной; |
| Info | – | дополнительное описание переменной. |
Функция регистрации неизменяемой переменной.
| VarInfo *dyn_DefineRemoteBufferArray( SysHandle *SrcHandle, SysHandle *DstHandle, long *Index ) | ||
| SrcHandle | – | исходный распределенный DVM-массив; |
| DstHandle | – | создаваемый буфер удаленного доступа; |
| Index | – | массив индексов элементов, для которых создается буфер. |
Функция регистрации буфера удаленного доступа как распределенного массива для нескольких элементов DVM-массива.
| VarInfo *dyn_DefineRemoteBufferScalar( SysHandle *SrcHandle, void *RmtBuff, long *Index ) | ||
| SrcHandle | – | исходный распределенный DVM-массив; |
| RmtBuff | – | адрес переменной, выступающей в качестве буфер удаленного доступа; |
| Index | – | массив индексов элемента, для которого создается буфер. |
Функция регистрации буфера удаленного доступа как скалярной переменной для элемента DVM-массива.
| void dyn_DestructReduct( VarInfo *Var ) | ||
| Var | – | указатель на описание переменной. |
Деструктор редукционной переменной. Вызывается при удалении описания переменной из таблицы переменных.
| void dyn_DestructPrivate( VarInfo *Var ) | ||
| Var | – | указатель на описание переменной. |
Деструктор приватной переменной. Вызывается при удалении описания переменной из таблицы переменных.
| void dyn_DestructReadOnly( VarInfo *Var ) | ||
| Var | – | указатель на описание переменной. |
Деструктор неизменяемой переменной. Вызывается при удалении описания переменной из таблицы переменных.
| void dyn_DestructDisArray( VarInfo *Var ) | ||
| Var | – | указатель на описание переменной. |
Деструктор распределенного DVM-массива. Вызывается при удалении описания переменной из таблицы переменных.
| void dyn_RemoveVar( void *addr ) | ||
| addr | – | адрес переменной. |
Функция удаления описания переменной с указанным адресом для текущего уровня выполнения.
| void dyn_InitializeSet( VarInfo *Var, size_t LI ) | ||
| Var | – | указатель на описание переменной; |
| LI | – | абсолютный индекс элемента массива. Равен -1 для скалярных переменных. |
Функция устанавливает флаг инициализации переменной или элемента массива.
| void dyn_InitializeClear( VarInfo *Var ) | ||
| Var | – | указатель на описание переменной. |
Функция сбрасывает флаг инициализации переменной или всех элементов массива.
| int dyn_InitializeCheck( VarInfo *Var, size_t LI ) | ||
| Var | – | указатель на описание переменной; |
| LI | – | абсолютный индекс элемента массива. Равен -1 для скалярных переменных. |
Функция возвращает значение флага инициализации переменной или элемента массива. Возвращает 1 при установленном флаге и 0 – иначе.
| void dyn_DisArrAcross(s_DISARRAY *Arr) | ||
| Arr | – | указатель на описание распределенного массива системы поддержки. |
Функция выставляет флаг использования распределенного DVM-массива в параллельном цикле с зависимостью по данным типа ACROSS. Для данного массива в пределах текущего параллельного цикла не будут производиться проверки на зависимость по данным.
| void dyn_DisArrCheckBounds( char *Operand, VarInfo *Var, size_t LI, byte isWrt, long Iter ) | ||
| Operand | – | имя переменной; |
| Var | – | указатель на описание переменной; |
| LI | – | абсолютный индекс элемента массива; |
| isWrt | – | тип доступа к элементу массива; |
| Iter | – | абсолютный номер текущей итерации параллельного цикла. |
Функция вычисляет локальную часть массива, принадлежащую текущей абстрактной машине, и проверяет принадлежность элемента массива этой локальной части или ее границам. Функция также проверяет корректность использования границ массива.
| void dyn_DisArrCheckSequential(char* szOperand, VarInfo* pVar, byte bIsWrt, long lLineIndex) | ||
| szOperand | – | имя переменной; |
| pVar | – | указатель на описание переменной; |
| bIsWrt | – | тип доступа к элементу массива; |
| lLineIndex | – | абсолютный индекс элемента массива. |
Функция проверяет корректность доступа к элементу распределенного DVM-массива в последовательной части программы.
| void dyn_DisArrCheckDataDepends( char *Operand, VarInfo *Var, size_t LI, byte isWrt, long Iter ) | ||
| Operand | – | имя переменной; |
| Var | – | указатель на описание переменной; |
| LI | – | абсолютный индекс элемента массива; |
| isWrt | – | 1, если элемент используется для записи. Иначе – 0; |
| Iter | – | абсолютный номер текущей итерации параллельного цикла. |
Функция проверяет зависимость цикла по данным при использовании элементов распределенного массива.
| byte dyn_DisArrCheckLimits( char *Operand, long LI, DISARR_INFO *Info ) | ||
| Operand | – | имя переменной; |
| LI | – | абсолютный индекс элемента массива; |
| Info | – | описание распределенного массива. |
Функция осуществляет проверку на выход за пределы распределенного массива. Возвращает 1, если элемент с абсолютным индексом LI находится в пределах границ локального блока массива.
| byte dyn_GetLocalBlock(s_BLOCK *DABlock, s_DISARRAY *DA, s_PARLOOP *PL) | ||
| DABlock | – | указатель на переменную, в которую будет записан вычисленный блок; |
| DA | – | указатель на описание распределенного массива системы поддержки; |
| PL | – | указатель на описания параллельного цикла системы поддержки. |
Функция вычисляет блок распределенного массива, обращения к элементам которого допустимы внутри текущей итерации параллельного цикла. Возвращает 0 в случае успешного вычисления блока.
| void dyn_DisArrDefineShadow(s_DISARRAY* pArr, s_BOUNDGROUP* pBndGroup, s_SHDWIDTH* pRtsShadow) | ||
| pArr | – | указатель на описание распределенного DVM-массива системы поддержки; |
| pBndGroup | – | указатель на описание группы границ системы поддержки; |
| pRtsShadow | – | указатель на описание теневых граней массива. |
Функция регистрирует описание теневых граней распределенного массива в системе динамического контроля и привязывает их к группе границ.
| void dyn_DisArrCompleteShadows(s_DISARRAY* pArr, s_BOUNDGROUP* pBndGroup) | ||
| pArr | – | указатель на описание распределенного DVM-массива системы поддержки; |
| pBndGroup | – | указатель на описание группы границ системы поддержки. |
Функция выставляет флаг завершения обмена границ распределенного массива, входящих в указанную группу.
| void dyn_DisArrClearShadows(DISARR_INFO* pInfo) | ||
| pInfo | – | описание распределенного массива. |
Функция удаляет все записи об обмене границ для указанного распределенного массива. Вызывается после модификации экспортируемых элементов массива.
| int dyn_FindShadowIndex(s_BLOCK* pBlock, long* sI, DISARR_INFO* pInfo) | ||
| pBlock | – | описание локального блока массива; |
| sI | – | массив индексов элемента распределенного DVM-массива; |
| pInfo | – | описание распределенного массива. |
Функция перебирает все описания теневых граней, связанные с распределенным массивом, и возвращает номер описания гранией, в пределах которых находится указанный элемент массива. Функция возвращает -1, если элемент массива не принадлежит ни одной из теневых граней массива.
5.6.3Параметры системы динамического контроля
Для управления динамическим отладчиком существует специальный набор параметров, с помощью которых пользователь может включать или отключать те или иные проверки, осуществлять настройку алгоритмов динамического отладчика для повышения эффективности его работы, управлять выдачей диагностик, задавать режимы работы при использовании метода сравнения результатов выполнения.















