Современные высокопроизводительные компьютеры
Программа для машины, не рассчитанная на использование конвейера, будет выглядеть примерно так: Loop: LD F0,0(R1) ;F0=элемент вектора ADDD F4,F0,F2 ;добавляет скаляр из F2 SD 0(R1),F4 ;запись результата SUBI R1,R1,#8 ;пересчитать указатель ;8 байт (в двойном слове) BNEZ R1, Loop ;переход R1!=нулю Для упрощения мы предполагаем, что массив начинается с ячейки 0. Если бы он находился в любом другом месте, цикл потребовал бы наличия одной дополнительной целочисленной команды для выполнения сравнения с регистром R1. Рассмотрим работу этого цикла при выполнении на простом конвейере с задержками, показанными на рис. 6.2. Если не делать никакого планирования, работа цикла будет выглядеть следующим образом: Такт выдачи Loop: LD F0,0(R1) 1 приостановка 2 ADDD F4,F0,F2 3 приостановка 4 приостановка 5 SD 0(R1),F4 6 SUBI R1,R1,#8 7 BNEZ R1,Loop 8 приостановка 9 Для его выполнения потребуется 9 тактов на итерацию: одна приостановка для команды LD, две для команды ADDD, и одна для задержанного перехода. Мы можем спланировать цикл так, чтобы получить Loop: LD F0,0(R1) 1 приостановка 2 ADDD F4,F0,F2 3 SUBI R1,R1,#8 4 BNEZ R1,Loop ;задержанный переход 5 SD 8(R1),F4 ;команда изменяется, когда 6 ;меняется местами с командой SUB1 Время выполнения уменьшилось с 9 до 6 тактов. Заметим, что для планирования задержанного перехода компилятор должен определить, что он может поменять местами команды SUB1 и SD путем изменения адреса в команде записи SD: Адрес был равен 0(R1), а теперь равен 8(R1). Это не тривиальная задача, поскольку большинство компиляторов будут видеть, что команда SD зависит от SUB1, и откажутся от такой перестановки мест. Более изощренный компилятор смог бы рассчитать отношения и выполнить перестановку. Цепочка зависимостей от команды LD к команде ADDD и далее к команде SD определяет количество тактов, необходимое для данного цикла.
|