Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Ассемблерные вставки в С++

8.0K
27 августа 2004 года
sha_visual
4 / / 22.08.2004
Если тело цикла, написанное на C++ и выполняющее арифметические действия, заменить на его дизассемблированный эквивалент, то такой цикл выполняется медленне. Почему?
3
27 августа 2004 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by sha_visual
Если тело цикла, написанное на C++ и выполняющее арифметические действия, заменить на его дизассемблированный эквивалент, то такой цикл выполняется медленне. Почему?


Может на пальцах покажешь? Пример кода в студию.

8.0K
28 августа 2004 года
sha_visual
4 / / 22.08.2004
Цитата:
Originally posted by Green

Может на пальцах покажешь? Пример кода в студию.



Извиняюсь за громоздкие листинги.

Вариант на С++
long lAddDiff=*piCurLef++ - *piCurRig++;
while(plCurDif<plEndDiL)
{ *plCurDif++=lAddDiff; }
while(plCurDif<plEndDiM)
{ *plCurDif++=*piCurLef++ - *piCurRig++; }
lAddDiff=*piCurLef++ - *piCurRig++;
while(plCurDif<plEndDiR)
{ *plCurDif++=lAddDiff; }

Вариант на ассемблере(мой самый быстрый)
__asm
{ mov eax,piCurLef
mov ebx,piCurRig
mov ecx,plCurDif

mov edx,lCount01
mov edi,[eax]
sub edi,[ebx]
add eax,4
add ebx,4
Lab00:
mov [ecx],edi
add ecx,4
dec edx
jnz Lab00

mov edx,lCount02
Lab02:
mov edi,[eax]
sub edi,[ebx]
add eax,4
add ebx,4
mov [ecx],edi
add ecx,4
dec edx
jnz Lab02

mov edx,lCount01
mov edi,[eax]
sub edi,[ebx]
Lab04:
mov [ecx],edi
add ecx,4
dec edx
jnz Lab04
}

Все переменные определены до приведенного здесь кода на С++ и ассемблере.
Если показанный здесь блок кода на С++ заменить на показанный здесь ассемблерный блок кода, то время счета увеличится на ~10%.

4.0K
28 августа 2004 года
wowa
41 / / 16.05.2004
Цитата:
Originally posted by sha_visual

long lAddDiff=*piCurLef++ - *piCurRig++;
while(plCurDif<plEndDiL)
{ *plCurDif++=lAddDiff; }
while(plCurDif<plEndDiM)
{ *plCurDif++=*piCurLef++ - *piCurRig++; }
lAddDiff=*piCurLef++ - *piCurRig++;
while(plCurDif<plEndDiR)
{ *plCurDif++=lAddDiff; }


Возможно компилятор умеет раскрывать циклы.
Попробуй написать код на асемблере равносильный этому, сделов в каждом цикле 2:
while(plCurDif<plEndDiL-1)
{ *plCurDif=lAddDiff;
plCurDif[1]=lAddDiff;
plCurDif+=2;}
if (plCurDif<plEndDiL-1)
{ *plCurDif++=lAddDiff; }

В нутри первого цикла типа так:
Lab00:
mov [ecx],edi
mov [ecx+4],edi
add ecx,8
dec edx
jnz Lab00

А во втором типа так:
Lab02:
mov edi,[eax]
mov edx,[eax+4]
sub edi,[ebx]
sub edx,[ebx+4]
mov [ecx],edi
mov [ecx+4],edx
add ecx,4
add eax,4
add ebx,4
cmp ecx,[plEndDiMm1] plEndDiMm1=plEndDiM-1
jxx Lab02

Так оно должно испольнятся быстрей

6.3K
19 сентября 2004 года
Denri
43 / / 12.08.2004
А кто вообще сказал, что на асме должно быть быстрее??
Скомпилируй сишный код с выдачей ассемблерного листинга (для MSVC ключ /Fa) и сравни со своим вариантом. Хороший оптимизирующий компилятор знает про такие инструкции, о которых ты и не вспомнил (stos*, cmov*, j*...). Кроме того, и это очень важно, С-компилятор может выравнивать код и данные в памяти по "удачным" местам, отчего скорость может сильно увеличиться.
На ассемблере имеет смысл писать только часто вызываемые, жутко "замороченные" функции, которые не под силу хорошо оптимизировать С-компилятору.
4
19 сентября 2004 года
mike
3.7K / / 01.10.2002
Кроме того, далеко не факт что в итоге в твоей программе цикл получается. Компиляторы ой как любят их разварачивать :)
6.3K
21 сентября 2004 года
Denri
43 / / 12.08.2004
Цитата:
Originally posted by mike
Кроме того, далеко не факт что в итоге в твоей программе цикл получается. Компиляторы ой как любят их разварачивать :)


Некоторые компиляторы умеют это делать. И уж точно не станут разорачивать цикл с неизвестным заранее числом итераций. Возможно, какие-то компиляторы (если "уговорить" ключами) умеют делать что-то подобное показанному выше, но я не слышал об этом.

1.8K
26 сентября 2004 года
gwg605
76 / / 06.03.2003
Цитата:
Originally posted by sha_visual


Извиняюсь за громоздкие листинги.

Все переменные определены до приведенного здесь кода на С++ и ассемблере.
Если показанный здесь блок кода на С++ заменить на показанный здесь ассемблерный блок кода, то время счета увеличится на ~10%.



Покажи как расчитываются следющие переменные:
plEndDiL, plEndDiM, plEndDiR. Думаю это даст ответ.

1.8K
26 сентября 2004 года
gwg605
76 / / 06.03.2003
Цитата:
Originally posted by sha_visual

Извиняюсь за громоздкие листинги.

Все переменные определены до приведенного здесь кода на С++ и ассемблере.
Если показанный здесь блок кода на С++ заменить на показанный здесь ассемблерный блок кода, то время счета увеличится на ~10%.



Я тут чуток поэксперементировал :). Смотри в присоединенном файле. Там три функции:
fc - "оригинальная" на С
fc1 - первая основная наметка, быстрее чем fc процентов на 5-6 (*
fc2 - добавил то что сумел вспомнить, быстрее оригинальной процентов на 20 (*

(* - я не совсем корректно измерял время выполнения функций, но под рукой нет VTune, поэтому проценты имеют некоторую погрешность.

Опять же результат может быть другой, при другом размере данных. У меня испрользуется достаточно маленький размер.

1.8K
26 сентября 2004 года
gwg605
76 / / 06.03.2003
Цитата:
Originally posted by Denri

Некоторые компиляторы умеют это делать. И уж точно не станут разорачивать цикл с неизвестным заранее числом итераций. Возможно, какие-то компиляторы (если "уговорить" ключами) умеют делать что-то подобное показанному выше, но я не слышал об этом.



Ну я видел компилятор под ARM который "сворачивал" два вложенных цикла в пару инструкций :)))

Правда это был баг оптимизатора, но... :)

Что касается компиляторов от МС и Интела, то они достаточно хорошо прощитывают циклы и если надо разворачивают их. Но иногода, бывают и у них косяки, если есть сомнения, надо посмотреть ассемблерный листинг кода вызывающщий сомнения, и станет ясно надо трогать или нет. В 99% случаев, трогать не стоит.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог