- •5. Программная конвейерная обработка и поддержка циклов
- •5.1. Краткий обзор
- •5.2. Терминология циклов и основная поддержка циклов
- •5.3. Оптимизация циклов
- •5.3.1. Развертывание цикла
- •5.3.2. Программная конвейерная обработка
- •5.4. Особенности поддержки циклов в архитектуре Intel Itanium
- •5.4.1. Ротация регистров
- •5.4.3. Переходы циклов с программной конвейерной обработкой
- •5.4.3.1. Переходы счетных циклов
- •5.4.2. Замечание об инициализации ротации предикатов
- •5.4.3.2. Пример счетного цикла
- •5.4.3.3. Переходы while-циклов
- •5.4.4. Краткий обзор терминологии
- •5.5. Оптимизация циклов в архитектуре Intel Itanium
- •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.5.5. Программная конвейерная обработка и предварительные загрузки
Предварительные загрузки позволяют удалять из цикла некоторый код, который, вероятно, будет инвариантным, и таким образом сокращать ресурсы, требуемые для цикла. Кроме того, использование предварительных загрузок позволяет сократить критический путь через итерации, позволяя уменьшить ИИ. Для получения дополнительной информации о предварительных загрузках см. главу 3 «Обращение к памяти». Однако должно учитываться ограничение при использовании предварительных загрузок с ротацией регистров. В данном обсуждении мы считаем, что ALAT имеет 32 элемента.
5.5.5.1. Ограничения емкости
Предварительная загрузка с адресатом, который является ротируемым регистром, указывает на разные физические регистры и выделяет новый элемент ALAT для каждой ядерной итерации. Например, нижеприведенный простой цикл заменяет 32 элемента ALAT в 32-ух итерациях.
L1: (p16) ld4.a r32 = [r8]
(p47) ld4.c r63 = [r8]
br.ctop L1;;
Чтобы избежать ненужных промахов ALAT, проверка загрузки либо проверка предварительной загрузки, должна быть выполнена прежде, чем предварительная загрузка вызовет замену проверяемого элемента. В нашем простом цикле не происходит ненужных промахов ALAT, потому что проверка загрузки делается в пределах 31-ой итерации предварительной загрузки. В примере ниже, промахи ALAT происходят для каждой проверки загрузки, потому что предварительная загрузка заменяет элемент непосредственно перед выполнением соответствующей проверки загрузки:
L1: (p16) ld4.a r32 = [r8]
(p48) ld4.c r64 = [r8]
br.ctop L1;;
5.5.5.2. Конфликты в alat
Использование предварительной загрузки для удаления вероятной инвариантной загрузки из цикла при продвижении другой загрузки внутрь цикла, в результате дает малую эффективность, если последние загрузки обращаются к ротируемому регистру. Предварительная загрузка, обращающаяся к ротируемому регистру, приведет, в конечном счете, к аннулированию элемента ALAT для инвариантной загрузки цикла. После этого, каждое выполнение проверки загрузки для инвариантной загрузки цикла приведет к промаху ALAT.
Когда более одной предварительной загрузки в цикле адресуется к ротируемым регистрам, то регистры должны быть назначены, а срок службы регистров управляется так, чтобы проверка загрузки, для отдельной предварительной загрузки Х, выполнялась бы прежде, чем любая другая предварительная загрузка аннулирует элемент, выделенный загрузкой X. Например, следующий цикл успешно обращается к ротируемым регистрам с двумя предварительными загрузками без какого бы то ни было промаха ALAT, поскольку две пары (предварительная загрузка – проверка загрузки) никогда не создадут одновременно более 32 активных элементов ALAT:
L1: (p16) ld4.a r32 = [r8]
(p31) ld4.c r47 = [r8]
(p16) ld4.a r48 = [r9]
(p31) ld4.c r63 = [r9]
br.ctop L1;;
Если код не может быть размещен так, чтобы избежать промахов ALAT, то может быть лучше назначить статические регистры для адресатов предварительных загрузок и развернуть цикл для явного переименования адресатов предварительных загрузок там, где это необходимо. Следующий пример показывает, как развернуть цикл, чтобы избежать использования ротации регистров. Цикл имеет ИИ равный 1, а проверка загрузки выполняется через один такт (и одну ротацию) после предварительной загрузки:
L1: (p16) ld4.a r33 = [r8]
(p17) ld4.c r34 = [r8]
br.ctop L1;;
Статические регистры могут быть назначены для адресатов загрузок, если цикл разворачивается вдвое:
L1: (p16) ld4.a r3 = [r8]
(p17) ld4.c r4 = [r8]
br.cexit L2;;
(p16) ld4.a r4 = [r8]
(p17) ld4.c r3 = [r8]
br.ctop L1;;
L2: //
Ротируемые регистры, все же могут использоваться для значений, которые не генерируются предварительными загрузками. Влияние такого разворачивания на эффективность кэша инструкций должно рассматриваться как часть стоимости продвижения загрузки.
