"Оптимизация для PENTIUM процессора" - читать интересную книгу автора TEST ECX, ECX
JZ SHORT L2 L1: MOV EAX, [ESI+4*EDX] ; u NEG EAX ; u MOV [EDI+4*EDX], EAX ; u INC EDX ; v (спаривание) CMP EDX, ECX ; u JB L1 ; v (спаривание) L2: Используя один регистр как счетчик и как индекс мы задействуем меньше инструкций в теле цикла, но он все еще исполняется за 4 такта, поскольку у нас есть две неспаренные инструкции. Счетчик, стремящийся к нулю --------------------------- Желая избавиться от инструкции CMP, из примера 3, мы могли бы обозначить конец цикла нулевым значением счетчика и использовать флаг нуля (ZF) для обнаружения конца цикла, как это мы делали в примере 2. Единственный путь сделать это - исполнить цикл наоборот, читая последние элементы первыми. Правда, кеш данных оптимизировался для доступа к поступающим подряд данным, а не наоборот, так что постоянные промахи кеша весьма вероятны, что бы избегать этого мы должны запускать счетчик от -N и увеличивать до нуля. А регистр базы должен указывать на конец массива, а не на начало: MOV ESI, [A] MOV EAX, [N] MOV EDI, [B] XOR ECX, ECX LEA ESI, [ESI+4*EAX] ; указатель на конец массива A SUB ECX, EAX ; -N LEA EDI, [EDI+4*EAX] ; указатель на конец массива B JZ SHORT L2 L1: MOV EAX, [ESI+4*ECX] ; u NEG EAX ; u MOV [EDI+4*ECX], EAX ; u INC ECX ; v (спаривание) JNZ L1 ; u L2: Теперь у нас пять инструкций в теле цикла, но на исполнение по прежнему тратиться 4 такта из-за плохого спаривания. (Если адреса и длины массивов постоянны, то мы можем сохранить два регистра заменяя A+SIZE для ESI и B+SIZE для EDI). А теперь давайте посмотрим как можно улучшить спаривание. Спаривание расчета с управлением цикла -------------------------------------- Мы можем захотеть ускорить цикл, спаривая инструкции его тела с инструкциями, |
|
|