- •5. Программная конвейерная обработка и поддержка циклов
- •5.1. Краткий обзор
- •5.2. Терминология циклов и основная поддержка циклов
- •5.3. Оптимизация циклов
- •5.3.1. Развертывание цикла
- •5.3.2. Программная конвейерная обработка
- •5.4. Особенности поддержки циклов в архитектуре IntelItanium
- •5.4.1. Ротация регистров
- •5.4.2. Замечание об инициализации ротации предикатов
- •5.4.3. Переходы циклов с программной конвейерной обработкой
- •5.4.3.1. Переходы счетных циклов
- •5.4.3.2. Пример счетного цикла
- •5.4.3.3. Переходы while-циклов
- •5.4.4. Краткий обзор терминологии
- •5.5. Оптимизация циклов в архитектуре IntelItanium
- •5.5.1. While-циклы
- •5.5.2. Циклы с инструкциями, имеющими предикаты
- •5.5.3. Циклы с множеством выходов
- •5.5.3.1. Преобразование циклов с несколькими выходами в циклы с одним выходом.
- •5.5.3.2. Конвейерная обработка с явными многократными выходами
- •5.5.4. Соображения о программной конвейерной обработке
- •5.5.5. Программная конвейерная обработка и предварительные загрузки
- •5.5.5.1. Ограничения емкости
- •5.5.5.2. Конфликты в alat
- •5.5.6. Предварительное разворачивание циклов для программной конвейерной обработки
- •5.5.7. Осуществление сокращений
- •5.5.8. Явный пролог и эпилог
- •5.5.9. Устранение избыточной загрузки в циклах
- •5.6. Итоги
5.3.2. Программная конвейерная обработка
Программная конвейерная обработка – это технология, которая стремится накладывать друг на друга итерационные циклы в манере, аналогичной аппаратной конвейерной обработке функциональных устройств. Каждая итерация разбивается на стадии с некоторым количеством (может быть и нулевым) инструкций в каждой стадии. Ниже показан концептуальный вид одной конвейерной итерации цикла исходногопримера, в котором каждая стадия длится один такт:
стадия 1:ld4 r4 = [r5],4
стадия 2:--- // пустая стадия
стадия 3:add r7 = r4,r9
стадия 4:st4 [r6] = r7,4
Ниже показан концептуальный вид пяти конвейерных итераций:
-
1
2
3
4
5
Такт
ld4
Х
ld4
Х+1
add
ld4
Х+2
st4
add
ld4
Х+3
st4
add
ld4
Х+4
st4
add
Х+5
st4
add
Х+6
st4
Х+7
Число тактов между началами последовательных итераций называется интервалом инициированияИИ. В нашем примере ИИ равно единице. Каждая стадия конвейерной итерации длится ИИ тактов. Большинство примеров в этой главе используют модульное планирование, которое является специфической формой программной конвейерной обработки, в которой ИИ является константой, и каждая итерация цикла имеет одно и то же планирование. Вероятно, что программные алгоритмы обработки кроме модульного планирования, могут извлекать выгоду из особенностей поддержки цикла. Поэтому примеры в этой главе обсуждаются, скорее в терминах программной конвейерной обработки, чем в терминах модульного планирования.
Как показано ниже, циклы программной конвейерной обработки имеют три фазы: пролог, ядро и эпилог:
-
1
2
3
4
5
Фаза
ld4
ld4
Пролог
add
ld4
st4
add
ld4
Ядро
st4
add
ld4
st4
add
st4
add
Эпилог
st4
В течение фазы пролога, для заполнения конвейера, новая итерация начинается каждые ИИ тактов (в нашем примере на каждом такте). В течение первого такта пролога, выполняется стадия 1 первой итерации. В течение второго такта, выполняются стадия 1 второй итерации и стадия 2 первой итерации и т.д. К началу фазы ядра конвейер заполнен. Выполняются: стадия 1 четвертой итерации, стадия 2 третьей итерации, стадия 3 второй итерации и стадия 4 первой итерации. В течение фазы ядра, каждые ИИ тактов, начинается одна новая итерация, а другая итерация завершается. В течение фазы эпилога, не начинается никаких новых операций, а завершаются итерации находящиеся в процессе выполнения, тем самым, опустошая конвейер. В нашем примере, в течение фазы эпилога завершаются итерации 3-5.
Программный конвейер кодируется как цикл, который очень отличается от первоначального исходного кода цикла. Для ясности, при обсуждении циклов и итераций циклов, мы используем термин исходный циклиисходная итерацияпри обращениях к первоначальному исходному коду цикла, а терминыядерный циклиядерная итерацияпри обращении к циклу, которые осуществляет программный конвейер.
В нашем примере загрузка из второй исходной итерации запускается прежде, чем используется результат первой загрузки. Таким образом, во многих случаях, загрузки из последовательных итераций цикла должны иметь разные приемные регистры, чтобы избежать перезаписывания еще не использованных значений. В традиционных архитектурах это требует развертывания ядра цикла и программного переименования регистров, в результате код расширяется. Кроме того, в традиционных архитектурах, отдельные блоки кода генерируются для фаз пролога, ядра и эпилога, в результате увеличивая расширение кода.
