Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 [ 61 ] 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88

ЕВХ, [МЕМ1]

ЕАХ, [МЕМ2]

uops

[МЕМЗ], ЕАХ

uops

EAX, [MEM2]

; 2

uops

(DO)

EBX, [MEMl]

(Dl)

, EBX

(D2)

[MEM3], EAX

uops

(DO)

Из вышеприведенных правил следует, что декодеры могут генерировать максимум шес1 мопов за такт, если первая инсфукция в каждой раскодировываемой фуппе разбивается на уопа, а другие две - на один каждая. Минимальное количество - это два мопа за такт, есл все инсфукции генерируют по два мопа, так что D1 и D2 никогда не используются.

Для максимальной производительности рекомендуется перефуппировать инсфукци оптимизируемой профаммы в блоки 4-1-1: инсфукции, которые генерирует 2 или 4 мог можно разбить на две простые одномопные инструкции, что не будет стоить ни такта:

MOV INC ADD ADD

Эта последовательность инсфукций занимает фи такта для раскодировки. Можн сэкономить один такт, перефуппировав инсфукции в две декодируемые фуппы:

ADD MOV INC ADD

Теперь декодеры генерируют 8 мопов за два такта, что удовлетворительно. На боле поздних стадиях конвейер может обрабатьшать только 3 мопа за такт, поэтому при скс рости декодирования высшей, чем эта, можно считать, что декодирование не являете узким местом. Тем не менее, сложности в механизме доставки могут задерживать раскс дирование (см. разд. 6.15), поэтому следует сфемиться к достижению скорости раскод! ровки, превышающей 3 мопа за такт.

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

Префиксы инсфукций также приводят к потере скорости раскодировки. У инсфу) ций могут быть префиксы следующих видов.

Префикс размера операнда требуется, когда вы используете 16-битный операн в 32-х битном окружении или наоборот. (Не считая инсфукций, у которых onepai ды могут быть только одного размера, например FNSTSW АХ). Префикс размер операнда вызывает потерю нескольких тактов, если у инструкции есть числовой К или 32-битный операнд, потому что размер операнда меняется префиксом.

ADD ВХ, 9 ; без потерь, так как операнд 8-битовый

MOV WORD PTR [МЕМ16], 9 ; есть потери, так как операнд 16-ти битовый

ADD ВХ, 9 ; без потерь, так как оп.еранд 8-битовый

MOV WORD PTR [МЕМ16], 9 ; есть потери, так как операнд 16-ти битовый

Последную инсфукцию следует заменить на MOV ЕАХ, 9

Мопы из декодеров через короткую очередь поступают в таблицу распределения р., гистров (RAT). Выполнение мопов осуществляется на временных регистрах, после чего результат записывается в постоянные регистры ЕАХ, ЕВХ и т. д. Целью RAT является указание мопам, какие временные регистры использовать и позволить переименование регистров (см. ниже).

После RAT мопы поступают в буфер перефуппировки (ROB). Целью ROB является неупорядоченное выполнение. Мопы остаются в области станции резервирования (reservation station), пока не станут доступны операнды, которые им необходимы. Если операнд мопа задерживается из-за того, что генерирующий его предыдущий мои еще не закончил свою работу, тогда ROB может найти дургой мои в очереди, чтобы сэкономить время.

Готовые к выполнению мопы посылаются в модули исполнения (execution units), которые сфуппированы вокруг пяти портов: порт О и I могут обрабатывать все арифметические операции, переходы и т. д. Порт 2 берет на себя операции считывания из памяти, порт 3 высчитывает адреса для записи в память, а порт 4 выполняет эту запись.

После того как инсфукция была выполнена, она помечается в ROB как готовая к удалению, после чего поступает в область удаления (retirement station). Здесь содержимое временных регисфов, использованных мопами, записывается в постоянные регисфы. Хотя мопы могут запускаться не по порядку, последний из них должен быть восстановлен при удалении.

6.14. Раскодировка инструкций (РРго, Р2 и РЗ)

Раздел 6.13 необходим для получения представления о работе раскодировщиков операций и понимания возможных способов доставки к ним инсфукций.

Декодеры могут обрабатывать фи инсфукции за такт, но только если соблюдены определенные условия. Декодер DO может обработать за один такт любую инсфукцию, которая генерирует до 4 мопов. Декодеры D1 и D2 могут обрабатывать только те инструкции, которые генерируют 1 могт и эти инсфукции не могут занимать больще 8 байт.

Резюмируем правила для декодирования двух или трех инсфукций за один такт.

первая инсфукци (DO) не должна генерировать больше 4-мопов;

вторая и фетья инсфукции не должны генерировать больше, чем по одному мопу;

вторая и фетья инструкции не могут занимать больше 8-байтов каждая;

И инсфукции должны содержаться внутри одного 16-байтного (см. разд. 6.15).

На длину инсфукции в DO не накладывается никаких офаничений, пока все три инсфукции помещаются в одном 16-байтном блоке.

Инсфукция, которая генерирует больше 4 мопов, фебует два или больше такта Д" раскодировки, и никакая другая инсфукция не может раскодировьшаться при это" параллельно.



Количество

1б-байтная

1б-байтная

задержка

выравнивание

декодируемых

граница в этом

фаница в первой

декодера

первого БДИ

групп в БДИ,

инструкции после

после перехода

содержащем

перехода

переход

на 16

к инструкции

на 16

к инструкции

к инструкции

к инструкции

на 16

к инструкции

3 или больше

к инструкции

3 или больше

к инструкции

3 или больше

к инструкции

3 или больше

к инструкции

Переходы задерживают доставку, поэтому цикл всегда занимает на два такта больше за выполнение, чем количество 16-ти байтных фаниц в цикле.

Следующая проблема с механизмом доставки инсфукций заключается в том, что новый БДИ не сгененирируется, пока предыдущий не будет полностью офаботан. Каждый БДИ может содержать несколько раскодировываемых фупп. Если БДИ длиной 16 байт заканчивали незавершенной инсфукцией, тогда следующий БДИ начнется в начале этой инсфукции. Первая инсфукция в БДИ всегда попадает в DO, а следующие две инсфукции направляются Dl и D2, если это возможно. Как следствие, D1 и D2 используются не совсем оптимально.

код сфуктурирован согласно правилу 4-1-1, а инсфукция, которая, как предполагалось, должна направиться в D1 или D2, оказьгаается первой инсфукцией в БДИ, тогда она попадает в Do, что ведет к потере одного такта. Вероятно, это недостаток архитектуры процессора.

[]ОТ«ри согласно табл. 6.5. Если удвоенный буфер доставляет только одну 16-байтную последовательность после перехода, тогда первый БДИ после перехода будет идентичен ей, т. е. рьфавнен по 16-байтной фанице. Другими словами, первый БДИ после перехода не будет яачинаться с первой инсфукции, но с ближайшего предшествующего адреса, кратного 16. £сли у удвоенного буфера есть время, чтобы зафузить две последовательности, тогда новый рДИ может пересечь 16-байтную фаницу и начаться с первой инсфукции после перехода. у правила кратко прорезюмированы в следующей таблице.

Таблица 6.5. Затраты на декодирование инструкций в БДИ

MOV WORD PTR [MEM16], AX ; никаких потерь,

; т.к. операция не требует немедленного исполнбн>.р

MOV ЕАХ, 9

MOV WORD PTR [МЕМ16], АХ ; нет потерь, так как нет числовых операндов

Префикс размера адреса используется при 32-битной адресации в 16-битном режиме или наоборот. Это редко требуется и этого следует избегать. Префикс размера адреса вызывает потери каждый раз, когда операнды используются явно, потому что их интерпретация изменяется с помощью префикса. Инструкции, оперирующие памятью неявно (например, строковые операции), не приводят к потерям, связанных с префиксом размера операнда.

Префиксы сегментов используются, когда вы обращаетесь к данным, находящимся не в cei менте данных по умолчанию. На РРго, Р2 и РЗ префиксы сегментов не приводят к потерям.

Префиксы повторения и префиксы закрытия (lock prefixes) не приводят к потерям пр декодировании.

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

6.15. Доставка инструкций (РРго, Р2 и РЗ)

Код доставляется в двойной буфер из кэща кода последовательностями по 16 байт Удвоенный буфер называется так, потому что он может содержать две таких последова тельности (см. разд. 6.13). Затем код берется из удвоенного буфера и передается декодерам поблочно (в основном по 16 байтов, но иногда он может быть и не выравнен по этой границе). Назовем такой блок блоком доставляемых инструкций БДИ. Если инструкция в БДИ пересекает границу в 16 байт, ее нужно изъять из обоих последовательностей удвоенного буфера и перефупприровать инструкции в них. Таким образом, удвоенный буфер нужен для того, чтобы позволить доставку инструкций, пересекающих барьер в 16 байт.

Удвоенный буфер может доставить одну 16-байтную последовательность за такт и может сгенерировать один БДИ за это же время. БДИ также могут иметь размер менее 16 байт за счет предсказания переходов (см. разд. 6.22).

К сожалению, удвоенный буфер недостаточно велик, чтобы обрабатывать инструкции, связанные с переходами без задержек. Если БДИ, который содержит инструкцию перехода, пересекает 16-байтную границу, двойному буферу требуется держать две последовательных 16-байтных последовательности, чтобы сгенерировать его. Если первая инструкция после перехода пересекает 16-байтную границу, тогда удвоенный буфер должен зафузить две новых 16-байтных последовательности кода, прежде чем он будет генерировать БДИ. Это означает, что в худшем случае декодирование первой инсфукции после перехода может б задержано на два цикла. Потери могут произойти из-за пересечения 16-байтных фан*"" в БДИ, содержащем переход. Возможно получение вышрыша в производительности, ей» имеется более одной раскодировьшаемой фуппы в БДИ, которая содержит переход, noTOW что это дает удвоенному буферу дополнительное время для доставки одной или двух послеЯ вательностей кода, следующих за переходом. Подобные выифыши могут компенсирова



адрес

инструкция

длина

мопы

ожидаемый

декодер

lOOOh

MOV ECX, 1000

lOOSh

LL: MOV [ESI], EAX

I007h

MOV [MEM], 0

lOllh

LEA EBX, [ЕАХ-ь200]

I017h

MOV BYTE PTR [ESI], 0

lOlAh

BSR EDX, EAX

lOlDh

MOV BYTE PTR [ESI-H],0

1021h

DEC ECX

I022h

JNZ LL

Предположим, что первый БДИ начинается по адресу lOOOh и заканчивается lOlOh до завершения инсфукции MOV [MEM], О, поэтому следующий БДИ начнется в 1007h и закончится 1017h. Поэтому фетий БДИ начнется по адресу 1017h и захватит весь остаток цикла. Число тактов, которое уйдет на раскодировку определяется количеством инсфукций, попадающих в DO. Всего их в цикле 5. Последний БДИ содержит фи раскоди-руемых блоков, включая последние пять инсфукций, и 16-байтную фаницу (1020h). Из табл. 6.6 видно, что первый БДИ будет начинаться со следующей инсфукции после перехода (метка LL) и заканчиваться 1015h. А именно внуфи инсфукции LEA, поэтому следующий БДИ будет начинаться с 101 Ih до 1021h, а последний - с 1021h и до самого конца. Теперь инструкции LEA и DEC совпопадают с началом БДИ, и поэтому они обе направляются в DO. В результате имеем 7 инсфукции в DO, и на раскодироваку цикла во втором повторении уходит 7 тактов. Последний БДИ содержит только одну фуппу, фебующую раскодировки (DEC ЕСХ / JNZ LL). Согласно табл. 6.6, следующий БДИ после команды перехода начнется с 16-байтной фаницы, т. е. lOOOh. Мы оказываемся в аналогичной ситуации, что на первой итерации, таким образом, раскодировка цикла занимает, соответственно, 5 и 7 тактов. Так как других узких мест нет, на выполнение цикла 1000 раз уйдет 6000 тактов. Если бы стартовый адрес был другим и первая или последняя инсфукции пересекали 16-байтную фаницу, в этом случае цикл занял бы 8000 тактов. Если нерсфуппировать инсфукции цикла так, чтобы команды для D1 или D2 не попадали в Начало БДИ, в этом случае выполнение цикла может занять всего 5000 тактов.

Вышеприведенный пример был преднамеренно построен так, что единственным узким местом является доставка инструкций и их раскодировка. Самый легкий путь избежать этой проблемы - это структурировать код, чтобы он генерировал больше 3 lonoB за такт, чтобы раскодировка не была узким местом, несмотря на приведенные по-гери скорости. В небольших циклах это возможно, поскольку достаточно легко оделировать и оптимизировать доставку инструкций и их раскодировку.

Из-за этого время, которое займет раскодировка определенного кода, может зависеть от тог(. где начнется первый БДИ.

Если скорость раскодирования инструкций критична и желательно избежать э-гц проблемы, нужно знать, где начинается каждый БДИ. Это довольно нудная работа. Вне чале нужно разделить сегмент на парафафы, чтобы знать, где находятся 16-байтные гр; ницы. Затем нужно взглянуть на ассемблерный листинг, чтобы увидеть, какова длиц каждой инструкции. (Рекомендуется изучить, как кодируются инструкции, чтобы умет предсказывать их длину.) Если известно, где начинается один БДИ, тогда можно найг где начинается другой. Если он кончается на фанице между инструкциями, значит, сл, дующий БДИ начнется здесь. Если он включает в себя часть инструкции, тогда след!, щий БДИ начнется с этой инструкции. (Здесь нужно подсчитывать только длины инсг рукций, не имеет значения, сколько мопов они генерируют.) Таким образом, можно обработать весь код и отметить, где начинается каждый из БДИ-блоков. Единственная проблема - это узнать, где находится первый БДИ. Вот несколько подсказок.

Первый БДИ после перехода, вызова или возврата из подпрофаммы может начинаться либо с первой, либо на ближайщей предшествующей 16-байтной фанице, согласно табл 6.5. Если выравнять первую инсфукцию так, чтобы она начиналась с 16-байтной фаницы, можно быть уверенным, что первый БДИ начнется именно с нее. Можно выравнять подобным образом код важных процедур и циклов, чтобы ускорить работу профаммы.

т Если комбинированная длина двух последовательных инсфукций больше 16 байтов, можно не сомневаться, что вторая из них не попадет в тот же БДИ, что и первая, следовательно, вторая инсфукция будет первой в в следующем БДИ. Можно использовать ее в качестве стартовой точки для того, чтобы найти, где начинаются следующие БДИ.

Первый БДИ, после неправильного предсказания перехода, начинается на 16-байтной фанице. Как объясняется в секции 6.22.2, цикл, который повторяется больше 5 раз, всегда будет приводить к неправильному предсказанию перехода при выходе из него. Первый БДИ посте такого цикла будет начинаться на ближайшей предшествующей 16-байтной фанице.

Есть также другие события, приводящие к подобному эффекту, например прерывания, исключения, самомодифирующийся код и такие инсфукции, как CPUID, FN и OUT.

Табл. 6.6. Пример расчета загрузки БДИ



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 [ 61 ] 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88