Как известно, инструкция xchg, оперирующая с памятью, занимается нехорошим делом: блокировкой шины. Иногда, конечно, это дело очень даже полезное, но гораздо чаще – нет. Давайте подумаем: чем можно заменить эту инструкцию (скажем, xchg [ecx],eax) для максимизации скорости? Конечно, первое, что приходит в голову – это: Код (ASM): mov edx,[ecx] mov [ecx],eax mov eax,edx Скорость взлетает ощутимо – проверено. Но! Тут используется дополнительный регистр! А если лишнего регистра нет? Что делать? Может, я откровенно туплю, но пока в голову не приходит ничего лучше, чем: Код (ASM): push eax push [ecx] pop eax pop [ecx] или Код (ASM): xadd [ecx],eax sub [ecx],eax Но второй вариант работает даже медленнее, чем первый (в цикле, по крайней мере)!!! Ах, да, есть же ещё: Код (ASM): xor eax,[ecx] xor [ecx],eax xor eax,[ecx] Он работает быстрее, чем xadd и чуть быстрее, чем push/pop в цикле (и тем более xchg), но скорость всё равно низкая... Задача №2 (усложнённая). Нам нужно обменять 2 элемента в памяти (а-ля xchg [ecx],[edx]). В распоряжении у нас максимум 1 регистр. То бишь такое не прокатит: Код (ASM): mov eax,[edx] mov ebx,[ecx] mov [edx],ebx mov [ecx],eax Тут, конечно, относительно быстрым будет: Код (ASM): mov eax,[ecx] xor eax,[edx] xor [edx],eax xor eax,[edx] mov [ecx],eax Но хочется большего!!! Покумекаем? p.s. Всяческие варианты с MMX/SSE/FPU (или каким-нибудь особенным набором инструкций) прошу не предлагать как основные решения. Как дополнительные – ну ок, сгодятся, хотя вариант наподобие первого (с 3-мя mov'ами) тут вполне очевиден.
Хотя, кстати говоря, код... Код (ASM): fld dword ptr [ecx] fld dword ptr [edx] fstp dword ptr [ecx] fstp dword ptr [edx] ...довольно шустр! И работает быстрее варианта с xor
Обмен значений 2-х переменных: Код (ASM): push [ecx] mov eax,[edx] pop [edx] mov [ecx],eax p.s. Но почему-то вариант: Код (ASM): push [ebp-4] mov eax,[ebp-8] pop [ebp-8] mov [ebp-4],eax работает чуть быстрее... кто-нибудь может объяснить: почему? Это при том, что в первом случае я делаю lea ecx,[ebp-4] + lea edx,[ebp-8] (они не учитываются в замере скорости, я их даже не удаляю для второго варианта). И даже если я заменю ecx/edx на esi/edi и размещу эти lea до rdtscp (которая производит сериализацию), результат тот же: варианты с [ebp-...] быстрее!
Ещё (про обмен регистра с памятью): Код (ASM): push eax mov eax,[ecx] pop [ecx] как будто бы немного быстрее работает (результаты тестов нестабильные, но ощущение такое)... И опять же, есть разница: используется ли именно [ecx] или [ebp-4].
Оптимизировал измерялку, получилось: Код (ASM): push [ecx] mov eax,[edx] mov [ecx],eax pop eax mov [edx],eax Быстрее (без цикла). И замена на [ebp-...] уже не влияет И код Код (ASM): push eax mov eax,[ecx] pop [ecx] получился ничуть не лучше, чем Код (ASM): push [ecx] mov [ecx],eax pop eax
Jin X, Можно было предсказать что профайл в этих случаях с заменой регистров должен быть одинаков, а ошибка в вашем профайлере. Так как это общий набор регистров(GPR) и без разницы эти замены, обработка их одинакова.