\subsection{Алгоритмы распараллеливания на общую память}

В этом разделе приведено подробное описание всех изменений, внесённых в систему SAPFOR для поддержки режима распараллеливания на общую память.

Как было описано ранее, проходы LOOP\_ANALYZER\_DATA\_DIST\_S* и CREATE\_TEMPLATE\_LINKS отвечают сугубо за распределение данных, поэтому работа по распараллеливанию на общую память начинается сразу с аналога прохода LOOP\_ANALYZER\_COMP\_DIST, который получил название LOOP\_ANALYZER\_NODIST.

На вход он также принимает АСД программы, множество структур \texttt{LoopGraph} и \texttt{FuncInfo} (но без графа измерений массивов). Отличия в работе начинаются со способа построения кортежей \textit{<цикл, массив, тип операции, номер измерения, A, B>}: при распределении данных такие записи не сохранялись для массивов, которые являются приватными в каком либо цикле программы. При распараллеливании на общую память есть возможность снять это ограничение и отображать на цикл все его неприватные массивы, даже если для других циклов они являются приватными.

Далее, появилась возможность обойти отображение витков цикла на распределяемый массив. Преобразованный алгоритм не запускает поиск наилучшего распределённого массива для распределения вычислений и не заполняет соответствующее поле в структуре \texttt{ParallelDirective}, хотя заполнение других полей, таких как ACROSS-зависимости, остаётся актуальным.

На следующем этапе работает новый проход SELECT\_ARRAY\_DIM\_CONF решающий проблему распараллеливания циклов, использующих секции массивов. Подробно проблема описывалась в предыдущей главе. На вход проход принимает множество структур \texttt{LoopNode} с заполненными полями параллельных директив \texttt{ParallelDirective}. Так же передаётся \textit{граф связей между массивами}. Вершинами этого ориентированного графа являются структуры \texttt{Array}. Дуги строятся по следующему правилу: пусть массив \textit{B} является формальным аргументом процедуры \textit{F}. Тогда в графе существует дуга от массива \textit{A} к \textit{B} в том и только том случае, если есть вызов процедуры \textit{F} с передачей секции массива \textit{A} в качестве фактического аргумента для \textit{B}.

Перед тем как рассматривать работу алгоритма, введём два понятия. Будем называть массив \textit{главным}, если он не является формальным аргументом функции, в которой он определён. Заметим, что в графе связей между массивами главными будут те и только те, которые не имеют входящих дуг. Также назовём \textit{конфигурацией} n-мерного массива кортеж из n чисел $a_{i}$, в котором $a_{i}$ является длинной i-го измерения.

Алгоритм работает следующим образом:

\begin{itemize}
    \item для каждого главного массива строится множество конфигураций массивов, достижимых из главного в графе связей массивов;

    \item для каждого главного массива выбирается лучшая конфигурация -- такая, которая соответствует наибольшему суммарному количеству элементов (суммарное кол-во элементов вычисляется как произведение элементов кортежа);

    \item рассматриваются все невыбранные конфигурации. Все циклы, которые используют хоть один массив, конфигурация которого не была выбрана на прошлом шаге, отстраняются от распараллеливания путём поднятия специального флага \texttt{hasAccessToSubArray} в структуре \texttt{LoopGraph} и удаления в ней директивы распараллеливания, если она была.
\end{itemize}

Таким образом, после данного прохода из распараллеливания будут исключены циклы, которые могут вызвать ошибку при выполнении программы.

Далее в проходе INSERT\_PARALLEL\_DIRS\_NODIST запускается алгоритм получения текстового представления директив распараллеливания \texttt{ParallelDirective}, который имеет следующие отличия от случая распараллеливания с распределением данных:

\begin{itemize}
    \item директивы распределения данных не используются проходом и не обрабатываются;

    \item в параллельных директивах не происходит конструирование клаузы \texttt{ON};
    
    \item не происходит конструирование клауз \texttt{SHADOW\_RENEW} и \texttt{REMOTE\_ACCESS};

    \item добавлено конструирование клауз \texttt{TIE}. Для заполнения списка отображаемых массивов используется сохранённая информация об обращениях к массивам с прохода LOOP\_ANALYZER\_NODIST.
\end{itemize}

В результате получается множество созданных директив \texttt{CreatedDirective}, содержащее только директивы распараллеливания на общую память.

Завершает распараллеливание на общую память вставка директив путём вызова кода прохода INSERT\_PARALLEL\_DIRS с передачей множества созданных директив \texttt{CreatedDirective}.