__asm в C++ быстродействие
Ну кому же не хочется ускорить свой код? - Взялся написать функцию скалярного произведения векторов.
mult - с использованием __asm
mult2 - аналогичная на чистом С++
C++ && __asm:
{
int out;
__asm
{
mov ESI, x
mov EDI, y
mov eax, 0 //sum
mov ecx, sz //цикл
label:
mov ebx, 1
imul ebx, [ESI]
imul ebx, [EDI]
add eax, ebx
add ESI, 4
add EDI, 4
//ecx--; (ecx==0)?outlabel : label
dec ecx
cmp ecx, 0
je outlabel
jmp label
// ------------- //
outlabel:
mov out, eax
}
return out;
}
С++ без __asm
{
int out=0;
for(int i=0;i<sz;i++)
{
out+=x*y;
}
return out;
}
Учет быстродействия:
{
int f[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
int g[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
time_t start;
start=time(0);
int r=1;
for(int i=0;i<100000000;i++)
{
r*=mult(&f[0],&g[0],20);
}
cout<<time(0)-start<<endl;
cout<<r<<endl;
start=time(0);
int t=1;
for(int i=0;i<100000000;i++)
{
t*=mult2(&f[0],&g[0],20);
}
cout<<time(0)-start<<endl;
cout<<t<<endl;
return 0;
}
Результаты:
Компиляция Debug
- 12сек/16сек. Т.е. __asm дало прибавку в 25% скорости.
Компиляция Release с опциями (/Ox,/Ot)
- 7сек/2сек. Т.е. чистый С++ оказался быстрее в 3 раза быстрее
Вопрос:
Как используя assembler добится роста быстродействия программы?
Как используя assembler добится роста быстродействия программы?
Надо дисиссемблировать то, что сделано с помощью C++ в релизе и изучить, чем их код лучше. Может переход по метке убрали - ведь в коде известно, сколько циклов будет - 20. Значит для быстродействия можно 20 раз повторить код, чтобы не тратить время на переход по метке.
Где ссылка на статью? Или читал бумажный вариант?
"Преждевременная оптимизация - корень всех зол." (с) Дональд Кнут
Оптимизировать методом научного тыка - грубейшая ошибка и пустая трата времени.
А уж низкоуровневая оптимизация должна применяться в самом крайнем случае, когда другие методы уже не помогают. И уж конечно надо разбираться в том, что ты делаешь. Твой "скоростной пример" изобилует ошибками оптимизации (лишнее умножение, др. лишние мат. операции).
Вот один из вариантов компиляции твоего кода (кстати, твой код больше в стиле C, а не "чистого C++"):
xor ecx,ecx
mov edx,dword ptr y[ecx]
imul edx,dword ptr x[ecx]
add ecx,4
add eax,edx
cmp ecx,28h
jl mult2+4
ret
и это ещё не самый быстрый вариант.
Меня всегда удивляла некоторая суровость по отношению к себе у некоторых программистов: им обязательно надо использовать самые рисковые и неудобные трюки, которые якобы улучшают программу.
Хотя, может быть пользователи за 3 процента в увеличении быстродействия программы готовы потерпеть самую жуткую ее глючность...
В нем где только не было этих ассемблерных вставок, за что я два месяца проклинал программистов, чьи шаловливые ручки все это написали. Нужно было переводить проект под x64, а эти самые вставочки не поддерживаются в 64-х битном компиляторе (VS2008). Приходилось разбирать весь этот бред без единого комментария и переводить на человеческий язык (т.е. на C++). А порой меня даже удыбало, когда встречал маленькие блоки, в которых кроме обнуления переменной ничего не делалось (для прикола чтоли?).
Ассемблер - язык более низкого уровня, чем С++ со всеми вытекающими последствиями переносимости - это огромный минус лично для меня, т.к. последнее время все чаще приходится делать кросс-платформенный код.
А если выжимать скорость, то без SSE не обойтись.
На моей памяти пожалуй только в одной программе без ассемблерного кода производительность заметно снижалась, что было критично. Но там использовались не вставки, которые уродуют код, а полноценные ассемблерные модули.
Это в этот раз. А в другой раз - 10 :), напримеор
Книга: Юрий Магда, "Использование ассемблера для оптимизации программ на С++"
MSVS2003(7.1)
Где-то читал, что это способно дать мин 50% прирост скорости.
Сожги ту книгу!!
К лешему такое чтиво. Взгляните на книжку "Техника оптимизации программ. Эффективное использование памяти" Касперского.
Кстати, как вы без профайлера-то оптимизируете код, переписывая с С++ на ассемблер?
Касперски он.
Ни один компилятор не способен настолько оптимизировать код, как бы он удовлетворил человека. Green прав - вариант твоего дизассемблированного кода (от компилятора) ещё не самый удачный, хотя и очень даже ничего... В любом случае, прироста добиться можно, но нужно ли это, когда на дворе вычислительные машины, стоящие у нас на столах способны вычислять погоду (утрирую). Лучше компилятора не напишешь, а намучаешься только, потеряешь время и может быть сорвёшь сроки.
Например тот код использует imul, а это требует немалого времени процессорного. Можно заменять на shl при определённых условиях, но кому это нужно? Если только для себя, то да, может и нужно, а вот заказчику глубоко пофиг, что ты там и как умножаешь, он прироста даже не заметит. Но ты будешь с гордостью смотреть в профилировщик и загоняться, что твой код похудел на пару тактов. Про это я и говорю.
Пользователем, а не профайлером.
P.S. Не сочтите за рекламу. Действительно хорошая вещь, пользуюсь на работе.