"Оптимизация для PENTIUM процессора" - читать интересную книгу автора

JNZ L1 ; v (спаривание)
NEG EAX
NEG EBX
MOV [EDI+4*ECX-8], EAX
MOV [EDI+4*ECX-4], EBX
L3:

Хитрость в том, что бы найти спаривающиеся инструкции, таким образом, что бы
не использовать счетчик цикла как индекс и реорганизовать цикл так, что бы
счетчик цикла увеличивался в предыдущем такте. Таким образом мы достигли
5 тактов для двух операций, приблизившись к лучшему из возможных решению.

Если кеширование данных является критическим, то можно увеличить скорость
объединив массивы A и B в одну структуру что бы каждое B[i] находилось после
соответствующего A[i]. Если структура массива выравнена, то по крайней мере
на 8, то B[i] будет всегда находиться в той же строке, что и A[i] и у вас
никогда не будет промахов кеша при записи B[i]. Конечно это приведет к
усложнению других частей программы, так что вы должны взвесить все
преимущества и недостатки.

Развертывание более чем в 2 раза
--------------------------------
Вы можете подумать, что исполнение более двух операций за одну итерацию
приведет к еще большей производительности цикла. Правда потери цикла не всегда
могут сводиться к одному такту за итерацию, так что развертывая цикл в 4 раза,
вместо 2 вы сохраните только 1/4 такта за итерацию, эффект за который вряд ли
стоит бороться. Только если потери не сводятся к одному такту и N велико
стоит думать о развертывании в 4 раза.

Недостатки через мерного развертывания цикла:
1. Вам необходимо вычислить остаток от деления N на R, где R - коофициент
развертки и выполнять этот остаток до или после основного цикла, что бы
сделать кол-во операций делимым на R. Это потребует дополнительного кода с
плохо предсказуемым ветвлением. И, разумеется, увеличиться тело цикла.
2. Код, обычно, требует больше времени при первом исполнении, чем при повторах
и большое тело цикла будет выполняться дольше первый раз, что актуально, если
N невелико.
3. Через мерный размер кода уменьшает эффективность кеша кода.

Обработка команд с 8 или 16 битными оперндами - частями 32 битных регистров
---------------------------------------------------------------------------
Если вам надо манипулировать с массивами 8 или 16 битных значений, то у вас
может возникнуть проблема с развертыванием цикла из-за того, что вы не сможете
добиться спаривания операций доступа к памяти. К примеру MOV AL,[ESI] /
MOV BL,[ESI+1] не спариться, если оба операнда лежат в пределах одного двойного
слова в памяти. Но существует более простой способ, призванный что бы
оперировать со всеми четыремя байтами в одном 32 битном регистре.

Следующий пример увеличивает на 2 каждый элемент массива байт.