Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
MProc / M9 / Оптимизация часть 5..doc
Скачиваний:
41
Добавлен:
16.04.2013
Размер:
260 Кб
Скачать

5.5.3.2. Конвейерная обработка с явными многократными выходами

Второй подход заключается в объединении трех последних инструкций в цикле в инструкцию br.cloop, а затем цикл конвейеризируется. Конвейер, использующий этот подход, показан ниже:

стадия 1: ld4.s r4 = [r5],4;; // ИИ = 1

стадия 4: ld4.s r9 = [r4];;

стадия 6: cmp.eq.unc p1,p0 = r9,r7

(p1) br.cond exit

br.cloop L1;;

В этом конвейере имеются пять спекулятивных стадий, потому что не спекулятивное решение инициализировать другую итерацию цикла, не может быть сделано до выполнения br.cond и br.cloop в стадии 6. Ниже показан код, осуществляющий этот конвейер в предположении, что индекс выхода равен 200.

mov lc = 204

mov ec = 1

mov pr.rot = 1 << 16;; // PR16 = 1, остальные = 0

L1:

ld4.s r32 = [r5],4 // Такт 0

(p21) chk.s r38, recovery // Такт 0

(p21) cmp.eq.unc p1,p0 = r38,r7 // Такт 0

ld4.s r36 = [r35] // Такт 0

(p1) br.cond exit // Такт 0

L2: br.ctop.sptk L1; // Такт 0

Когда, либо br.cond либо br.ctop выходит из ядерного цикла – завершается последняя исходная итерация. Таким образом, ЕС инициализировано в 1 и нет явного блока эпилога, сгенерированного для выхода. Регистр LC инициализирован к пяти (после 199 шагов) потому, что имеются пять спекулятивных стадий. Цель первых пяти выполнений br.ctop – это просто сохранить движение цикла до тех пор, пока не будет сгенерирован первый допустимый предикат для br.cond. При каждом таком выполнении LC декрементируется, поэтому, для компенсации, к числу инициализации LC должна быть добавлена пятерка.

При втором подходе достигается меньший ИИ. Этот конвейерный код будет также работать, если LC инициализирован к 199, а ЕС инициализирован к 6. Однако если будет принят преждевременный выход, то LC будет декрементирован слишком много раз, и будет нуждаться в корректировке, если он используется в адресате преждевременного выхода. Если есть какой-нибудь эпилог при принятии раннего выхода, то этот эпилог должен быть явным.

5.5.4. Соображения о программной конвейерной обработке

Могут быть случаи, когда не желательно конвейеризировать цикл. Программная конвейерная обработка увеличивает производительность итераций, но может увеличить время, требуемое для завершения отдельной итерации. В результате, циклы с очень маленькими индексами завершения могут получить меньшую эффективность при конвейерной обработке. Например, рассмотрим следующий цикл:

L1: ld4 r4 = [r5],4 // Такт 0

ld4 r7 = [r8],4;; // Такт 0

st4 [r6] = r4,4 // Такт 2

st4 [r9] = r7,4 // Такт 2

br.cloop L1;; // Такт 2

Далее приведен возможный конвейер при ИИ = 2:

stage 1: ld4 r4 = [r5],4 // Такт 0

ld4 r7 = [r8],4;; // Такт 0

--- // пустой такт

stage 2: --- // пустой такт

st4 [r6] = r4,4 // Такт 3

st4 [r9] = r7,4;; // Такт 3

В исходном цикле, одна итерация заканчивается каждые три такта. В цикле с программной конвейерной обработкой требуется четыре такта для завершения первой итерации. После этого итерации завершаются каждые два цикла. Если индекс выхода – два, то время выполнения обеих версий цикла одно и то же – 6 тактов. Если средний индекс выхода из цикла меньше двух, то версия цикла с программной конвейерной обработкой медленнее исходного цикла.

Кроме того, не желательно организовывать конвейер для цикла с плавающей точкой, который содержит вызов функции. Число регистров с плавающей точкой используемых циклом не известно до тех пор, пока цикл не будет превращен в конвейер. В полученном конвейере может быть трудно, найти пустые слоты для инструкций, необходимых для сохранения и восстановления регистров с плавающей точкой на время вызова функции.