Скачиваний:
58
Добавлен:
16.04.2013
Размер:
260.1 Кб
Скачать

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 тактов. Если средний индекс выхода из цикла меньше двух, то версия цикла с программной конвейерной обработкой медленнее исходного цикла.

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