Использование характерных особенностей ЦПОС
В этом разделе приведены преобразования, несложные для реализации, но представляющие интерес, поскольку опираются на внутренние особенности ЦПОС.
Раскладка локальных переменных по банкам памяти. В основе данного оптимизирующего преобразования лежит тот факт, что гарвардская архитектура предоставляет возможность параллельного доступа к двум ячейкам, при условии, что они находятся в различных памятях. Таким образом, появляется возможность ускорить доступ к данным при одновременном сокращении размера программного кода [11].
Раскладка данных в свою очередь приводит к трём взаимосвязанным проблемам:
- Необходимо установить связи между различными элементами данных в контексте раскладки по разным памятям. Это включает в себя определение пар элементов данных потенциально способных находиться в различных банках памяти.
- Необходимо определить функцию стоимости для каждой связи
- Необходимо задать правила таким образом, чтобы удовлетворить как можно большему количеству разделяющих связей, тем самым достигнув наибольшей общей производительности.
Частичное дублирование данных [11] оказывается полезным для оптимизации работы с участками кода подобными приведённому ниже:
for(n=1; n<r; n++) { R[n] +=signal[n] * signal[n+m]; }
Подобный код используется, в частности, при вычислении функции автокорелляции, что нередко встречается в алгоритмах для ЦПОС. Особенность этого фрагмента в том, что происходит одновременное обращение к двум элементам одного и того же массива.
Данный фрагмент можно существенно ускорить за счёт дублирования значений
signal[n] в двух банках памяти. Найти массивы-кандидаты на дублирование несложно – области жизни двух обращений к одному и тому же массиву должны пересекаться.
Дублирование данных не всегда приводит к повышению производительности. В частности, если в последствии не удастся запаковать оба обращения в одну инструкцию. В этом случае дублирование данных только ухудшает программу.
Кроме того, дублирование может усложнить работу с прерываниями.
Если запись различных двух копий одних и тех же данных окажутся разнесёнными по различным инструкциям теоретически возникает возможность аппаратного прерывания между ними, а значит данные в двух копиях могут оказаться в несогласованном состоянии.
Использование аппаратной поддержки циклов. В ЦПОС присутствует поддержка аппаратных циклов. Генерация кода для этого случая, в принципе, тривиальна: если имеется информация об исходном цикле, необходимо проверить что этот цикл удовлетворяет некоторым условиям:
- внутри цикла нет ветвлений и вызовов процедур
- границы цикла известны и фиксированы
- тело цикла не зависит напрямую от переменной индукции
- тело цикла не содержит запрещённых инструкций
В данном случае важно, что компилятор сохраняет информацию о циклах до довольно поздней стадии: стадии, когда уже сгенерирован код. Например, в SPAM это достигается за счёт того факта, что SUIF, используем в качестве front-end, позволяет «протаскивать» информацию об исходных циклах через весь слой машиннонезависимых оптимизаций и генерации кода.