Поменяйте местами 2 переменные в C ++ с ассемблерным кодом - PullRequest
3 голосов
/ 30 мая 2011

У меня есть огромная функция, которая сортирует очень большое количество int данных. Код работает нормально, за исключением того факта, что он медленнее, чем должен быть. Мой первый шаг к решению этой проблемы - поместить код asm внутрь C++. Как я могу поменять 2 переменные, используя asm? Я пробовал это:

_asm{ push a[x]; push a[y]; pop a[x]; pop a[y];}

и это:

_asm(mov eax, a[x];mov ebx,a[y]; mov a[x],ebx; mov a[y],eax;}

но оба терпят крах. Как я могу сэкономить время на этих развязках? Я использую VS_2010

Ответы [ 4 ]

4 голосов
/ 30 мая 2011

В общем, очень сложно сделать лучше, чем ваш компилятор, с простым кодом, подобным этому.

Компилятор, когда сталкивается с операцией подстановки целых чисел, обычно выдает код, подобный этому:

mov eax, [x]
mov ebx, [y]
mov [x], ebx
mov [y], eax

Прежде чем пытаться переопределить, сначала проверьте, что на самом деле генерирует компилятор.Если это что-то вроде этого, не беспокойтесь идти дальше;Вы не сможете добиться большего успеха, чем это.Более того, если вы оставите это для компилятора, он может, если сразу после этого использовать эти переменные, выбрать повторное использование одного из этих регистров, чтобы также сэкономить на переменных загрузках / хранилищах.Это невозможно при ручной сборке;компилятор должен перезагрузить переменные после черного ящика, который закодирован вручную.

Обратите внимание, что последовательность push / push / pop / pop, вероятно, будет намного медленнее;он не только добавляет дополнительные четыре операции с памятью в стек, но также вводит зависимости от указателя стека, исключая любую возможность конвейерной обработки.С простой последовательностью mov возможно, по крайней мере, выполнить пару чтений и пару записей параллельно, если они находятся в разных банках памяти, или одна находится в кэше, и т. Д. Это также не приводит к остановкам в стекеуказатель в последующем коде.

Таким образом, вы не должны пытаться микрооптимизировать стоимость обмена;вместо этого уменьшите количество выполненных обменов .Существует множество алгоритмов сортировки , каждый из которых имеет немного отличающиеся характеристики.Вы можете обнаружить, что некоторые из них лучше (вызывают меньше свопов) в вашем наборе данных, чем другие.

2 голосов
/ 30 мая 2011

Что заставляет вас думать, что вы можете производить более быструю сборку, чем оптимизирующий компилятор?
Даже если вы заставите его работать должным образом, все, чего вы, вероятно, достигнете, - запутать оптимизатор, чтобы он создавал еще более медленный код.

1 голос
/ 30 мая 2011

Когда вы выполняете встроенную сборку, вы можете изменить вещи так, чтобы предположения, сделанные компилятором относительно содержимого регистра, больше не были верными.Часто EAX используется для передачи параметра или возврата значения, поэтому очистка EAX может не иметь большого эффекта, но вы забили EBX и не вернули его, и это может вызвать проблемы.Попробуйте нажать EBX, прежде чем использовать его, а затем нажмите его, когда закончите.

1 голос
/ 30 мая 2011

Вы можете использовать имена переменных, имена функций и метки в коде сборки в качестве символов. Обратите внимание, что такие вещи, как a[x], не являются таким допустимым символом.

Написание более эффективного кода требует навыков и знаний, использование asm не обязательно поможет вам в этом.

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

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