allasm.ru |
|
10.1 Совершенное спаривание У PPlain и PMMX есть два конвеера, выполняющих инструкции, которые называются U-конвеер и V-конвеер. В определенных условий можно выполнить две инструкции одновременно, одну в U-конвеере, а другую в V-конвеере. Это практически удваивает скорость. Поэтому имеет смысл перегруппировать ваши инструкции и сделать их спариваемыми. Следующие инструкции могут находится в любом конвеере.
Следующие инструкции спариваемы только в U-конвеере:
Все другие целочисленные инструкции могут выполняться только в U-конвеере и не могут спариваться. Две следующие друг за другом инструкции будут спариваться, если соблюденые следующие условия:
Примеры:
3. Неполные регистры считаются полными регистрами. Пример:
пишут в разные части одного и того же регистра, не спаривается. 4. Две инструкции, пишущие в разные части регистра флагов могут спариваться не смотря на правила 2 и 3. Пример:
5. Инструкция, которая пишет в регистр флагов может спариваться с условным переходом несмотря на правило 2. Пример:
6. Следующая комбинация инструкций может спариваться несмотря на тот факт, что обе изменяют указатель на стек:
7. Есть ограничения на спаривание инструкций с префиксами. Есть несколько типов префиксов:
На PPlain инструкция с префиксом может выполняться только в U-конвеере, кроме ближних условных переходов. На PMMX инструкции с префиксами размера операнда, размера адреса или 0FH могут выполняться в любом конвеере, в то время как инструкции с префиксами сегмента, повторения или LOCK могут выполняться только в U-конвеере. 8. Инструкция, в которой используется одновременно адресация со смещение и числовые данные на PPlain не спариваются, на PMMX могут спариваться только в U-конвеере:
(Другая проблема, связанная с подобными инструкциями, выполняющимися на PMMX, заключается в том, что такие инструкции могут быть длинее семи байтов, а это приводит к невозможности раскодировки больше одной инструкции за такт, подробнее это объясняется в главе 12.) 9. Обе инструкции должны быть заранее загружены и раскодированы. Это объяснение в главе 8. 10. Есть специальные правила спаривания для инструкций MMX на PMMX:
10.2 Несовершенное спаривание Бывают ситуации, когда две спаривающиеся инструкции не будут выполняться одновременно или будут частично рассинхронизированы во времени. Пока обе инструкции не выполняться (каждая в своем конвеере) ни одна другая инструкция не начнет выполняться. Несовершенное спаривание возникает в следующих случаях:
Примеры:
Спариваемые целочисленные инструкции, которые не обращаются к памяти, требуют один такт для выполнения, кроме неправильно предсказанных переходов. Инструкции MOV, читающие или пишущие в память также занимают один такт, если данные находятся в кэше и правильно выравненны. Нет потери в скорости при использовании сложных способов адресации, такие как смещение и масштабирование. Спариваемая целочисленная инструкция, которая читает из памяти, делает какие-то вычисления, а затем сохраняет результат в регистрах или флагах, занимает 2 такта (инструкции чтения/модифицирования). Спариваемая целочисленная инструкция, которая читает из памяти, делает какие-то вычисления, а затем записывает результат обратно в память, занимает 3 такта (инструкции чтения/модифицирования/записи). 4. Если инструкция чтения/модифицирования/записи спаривается с инструкцией чтения/модифицирования или чтения/модифицирования/записи, тогда они спарятся несовершенно. Количество тактов, которые потребуются для выполнения такой пары, даны в следующей таблице:
Пример:
B Когда две спаривающиеся инструкции требуют дополнительное время для выполнения из-за неоптимального использования кэша, невыровненности или неправильно предсказанного условного перехода, они будут выполнятся дольше, чем каждая инструкция, но меньше, чем сумма времени, требующаяся на выполнение каждой из них по отдельности. 6. Спариваемая инструкция плавающей запятой и следующая за ней FXCH повлекут несовершенное спаривание, если следующая инструкция не является инструкцией плавающей запятой. Чтобы избежать несовершенного спаривания, вы должны знать, какие инструкции пойдут в U-конвеер, а какие - в V-конвеер. Вы можете выяснить это, просмотрев свой код и поискав инструкции, которые неспрариваются, или спариваются только в определенном конвеере, или не могут спариваться в силу одного из вышеизложенных правил. Несовершенное спаривание можно зачастую избежать, реорганизовав свои инструкции. Пример:
Здесь две инструкции MOV формируют несовершенную пару, потому что обе обращаются к одной и той же области в памяти, поэтому последовательность займет 3 такта. Вы можете улучшить этот код, реорганизовав инструкции так, чтобы 'INC ECX' спаривалась с одной из инструкции MOV.
Пара 'INC EBX / MOV ECX,[EAX]' несовершенная, потому что следующая инструкция приводит к задержке AGI. Последовательность занимает 4 такта. Если вы вставите NOP или какую-нибудь другую инструкцию, чтобы 'MOV ECX,[EAX]' спаривался с 'JMP L1', последовательность займет только три такта. Следующий пример выполняется в 16-ти битном режима, предполагается,что SP делится на 4:
Инструкции PUSH формируют две несовершенные пары, потому что оба операнда в каждой паре обращаются к одному и тому же слову в памяти. 'PUSH BX' могла бы совершенно спариться с PUSH CX (потому что они находятся по разные стороны от границы, отделяющей двойные слова друг от друга), но этого не происходит, потому что она уже спарена с PUSH AX. Поэтому последовательность занимает 5 тактов. Если вы вставите NOP или другую инструкцию, чтобы 'PUSH BX' спаривалась с 'PUSH CX', а 'PUSH DX' с 'CALL FUNC', последовательность займет только 3 такта. Другой путь разрешения данной проблемы - это убедиться, что SP не кратен четырем. Правда, узнать это в 16-ти битному режиме довольно сложно, поэтому лучший выход - использовать 32-х битный режим. |