Оптимизация, C++, Asm
for(int i=0;i<10;i++)
{
}
по мне не должен, но вот не могу быть уверен на все 100% при каких условиях что компилятор с генерирует

а вы бы это к какой категории отнесли?
В стандарте не сказано обратного, значит может.
Может ли такое выражение изменить значение флага CF?цикл не есть выражение
for(int i=0;i<10;i++)
{
}
ответ: разумеется может (ибо как справедливо заметил : в стандарте не сказано обратного и вообще там ничего не сказано про регистры - значит любой из регистров может изменится).
А в данном случае на x86 платформе флаг CF не только может, а с очень большой вероятностью изменится на 0 по окончании цикла (вследствие операции сравнения с 10) и скорее всего CF=1 в начале тела цикла (хотя все это разумеется зависит от реализации: оптимизатор может такой простой цикл раскрутить, а этот пустой цикл вовсе удалить). Но к языку C++ это уже не имеет отношения, а только к конкретной его реализации.
(например вследствие операции сравнения с 10)правильно, забыл что cmp и sub, меняют значение флага CF по которому и определяет прыгать или нет.
Буду стараться избегать такого.
Заметил, что компилятор VC++2003 почему то любит именно команду sub
но вот тут есть один момент
for(int i=0;i<repCount;i++)
{
__asm rcl tralala[i],1
}
где repCount является константой и не большой величиной
в таком случае оптимизатор может в место повторного использования одного rcl вызвать их последовательно, что значительно повысит скорость
__asm rcl tralala[0],1
__asm rcl tralala[1],1
__asm rcl tralala[2],1
....
в таком случае заработает по задуманному
или может я ошибаюсь?
а вообще стоит такие трюки делать?

но вот тут есть один моментда раскруткой цикла (loop unrolling) называется
for(int i=0;i<repCount;i++)
{
__asm rcl tralala[i],1
}
где repCount является константой и не большой величиной
в таком случае оптимизатор может в место повторного использования одного rcl вызвать их последовательно, что значительно повысит скорость
__asm rcl tralala[0],1
__asm rcl tralala[1],1
__asm rcl tralala[2],1
....
в таком случае заработает по задуманномуконечно не стоит
или может я ошибаюсь?
а вообще стоит такие трюки делать?
сказать, что это не портируемо - это будет очень мягко сказано: даже от опций одного и того же компилятора будет зависеть заработает или не заработает.

отредактировал предыдущий пост еще не прочитав ваш ответа мне показалось, что я ваше сообщение не внимательно прочитал посмотрев его второй раз
Я реализую всякие криптоалгоритмы, знаете как там важна скорость, всё время с битами работаю.
На голом ассемблере ничего писать не люблю =(
Пытаюсь создать один общий шаблон класс Register там надо всякие сдвиги делать... Универсальные ясные, надёжные алгоритмы которые и асму не требует, работающие с регистром любой длины мягко говоря не очень эффективны.
Хочу умудриться сделать так чтоб для регистра любой длины генерировал максимально эффективный код.
Всякие макросы использую... всякие трюки пытаюсь делать.
Не очень получается.
Видимо для каждого отдельного случая буду писать отдельный код для макс скорости с использованием асмы без for-ов =(
Мне кажется, что в наши дни использование ассемблера вместо Си во многих задачах даёт выигрыш дай бог в 2-10%, при условии хорошо написанного кода. Зато код на Си будет иметь меньше ошибок и будет более понятным.
Также стоит поддержать hyperthreading.
и то, и другое - тебе может дать выигрыш в разы, при использование asm-а (как правильно заметил ) ты скорее всего выиграешь только ~10%
Нет, он проиграет 30%. Компилятор встретив __asm в функции не оптимизирует эту функцию.

Разумеется не забывай, что компилятор может изменить любые регистры между ассемблерными блоками, так что очень часто придется помещать большую часть кода в один __asm блок. Короче MSDN все расскажет.
На очень маленьких задачах с этим ещё можно согласиться. (Хотя я всё ещё встречаю программистов, которые не умеют быстро копировать блоки памяти на ассемблере.) Большая задача с ассемблерными вставками скорее всего выродится в в нечитабельную программу, которую очень трудно поддерживать, модифицировать и исправлять.
Его писать две недели, а потом ещё три недели оптимизировать со справочником в зубах, переставляя команды так и эдак.
Большая задача с ассемблерными вставками скорее всего выродится в в нечитабельную программу, которую очень трудно поддерживать, модифицировать и исправлять.только если писать через ж...
простите мой французский
Есть же тулы специальные. Разве под современный проц реально в уме представлять как поток команд в проце выполняется?
Его писать две недели, а потом ещё три недели оптимизировать со справочником в зубах, переставляя команды так и эдак.нафиг это надо команды переставлять так и эдак? Все равно для всех нынешних и будущих процов не оптимайзнешь идеальным образом, и ИМХО практики минимизации количества доступов к памяти, инструкций и используемых регистров (в таком порядке приоритета) вполне достаточно (ну еще плюс избегание использования сложных команд как интел завещал чтобы достаточно большой ассемблерный блок работал близко к идеалу, но могу и ошибаться.
во многих задачах даёт выигрыш дай бог в 2-10%,у меня не тот случай
в C++ насколько я знаю существуют всего на всего 2 оператора для сдвига регистров >>,<<. Этого мне мало, чтоб этими 2 операторами мне добиться желаемого я должен всякие битовые маски использовать... что требует множество дополнительных тактов, мне нужен rcl,rcr,shl,shr,jc,jnc чтоб я мог построить нечто намного быстрое, ключ к хорошему резултату будет не то что я просто возьму и перепишу из C в Асму и мучаясь добъюсь результата 5-10% делая то что оптимизатор делает, а именно используя rcl,rcr... чего в C насколько я знаю нет, что и вообще изменит алгоритм.
Нет, он проиграет 30%. Компилятор встретив __asm в функции не оптимизирует эту функцию.даже если она объявлена как inline?
поясните пожалуйста, очень интересно узнать почему.
a=b<<(32-s)|b>>s;

И в чем проблема найти библиотечку, которая делает это за тебя, используя для этого - все возможности процессора?
Я не сомневаюсь в правильности работы этого кода, мне интересно, сворачивает ли это компилятор в нормальный человеческий rol или ror
хмм меня тоже заинтересовало, сейчас проверим
int a = 0x1;
int b = 0x2;
int s = 0x4;
void main
{
a=b<<(32-s)|b>>s;
}
результат в режиме release
00401000 mov edx,dword ptr [s (407038h)]
00401006 mov eax,dword ptr [b (407034h)]
0040100B push esi
0040100C mov ecx,20h
00401011 mov esi,eax
00401013 sub ecx,edx
00401015 shl esi,cl
00401017 mov ecx,edx
00401019 sar eax,cl
0040101B or esi,eax
0040101D mov dword ptr [a (407030h)],esi
00401023 xor eax,eax
00401025 pop esi
00401026 ret
Что-то в этом духе я и предполагал. А чем компилял?
Ms. Visual C++ 7 2003 .NET
Инлайн тоже не оптимизирует, сам с этим разок столкнулся. Нужно было сначала умножить и могло получится число большее 0xffffffff, а потом взять остаток от деления. Чтобы не гемороится решил написать на асме и от этого скорость кода упала в 8 раз по сравнению с хитрожопным выриантом вычисления остатка. Код кроме вычисления остатка оставался тем же самым.
int a=123;
int s=7;
int b;
int main
{
b=a<<s|a>>(32-s);
}
Собирал с -O3. Пробовал без оптимизации - примерно так же получается.
push ebp
mov ebp , esp
push ebx
push eax
mov ebx , 0x80493E0
mov eax , 0x080493DC
mov cl , bl
mov edx , eax
shl edx , cl
mov ecx , 0x20
sub ecx , ebx
sar eax , cl
or edx , eax
and esp , 0xF0
mov 0x80494DC , edx
mov ebx , [ebp-0x04]
leave
ret
встретив asm в функции все известные мне компиляторы C++ забивают на inline.
с чего вы взяли, что у вас не тот случай? Как измерите время выполнения так и сможете сказать какой у вас случай.во многих задачах даёт выигрыш дай бог в 2-10%,у меня не тот случай
в C++ насколько я знаю существуют всего на всего 2 оператора для сдвига регистров >>,<<. Этого мне мало, чтоб этими 2 операторами мне добиться желаемого я должен всякие битовые маски использовать... что требует множество дополнительных тактов, мне нужен rcl,rcr,shl,shr,jc,jnc чтоб я мог построить нечто намного быстрое, ключ к хорошему резултату будет не то что я просто возьму и перепишу из C в Асму и мучаясь добъюсь результата 5-10% делая то что оптимизатор делает, а именно используя rcl,rcr... чего в C насколько я знаю нет, что и вообще изменит алгоритм.
Не уж то в вашем криптографическом алгоритме нет ничего кроме ролов?
Даже если там несколько раз встречаются ролы, и проверки сдвинутого за границу числа бита, все равно несмотря на кучу лишних инструкций хороший C алгоритм (откомпиленый хорошим C компилятором - не C++) обычно работает примерно на 5-20% хуже хорошего ассемблерного кода (а для задач "удобных" для реализации на C к которым ваша не относится может даже на какой-то процентик лучше, если не заморачиваться очень тщательно над оптимизацией ассемблерного кода).
Это проверенный факт, а не пустые предположения. Я лично впрочем ради этих 5-20% все равно стараюсь, но C версия почти обязательна все равно (потому, что это портируемый код не ограниченный виндой и x86 архитектурой).
Известные мне хорошие компиляторы на которые я ссылаюсь - это GCC-2.95.3, GCC-4.0, Intel C Compiler (который легко встраивается в VS, являясь лучшей альтернативой MSVC).
Правда восьмой интеловский компилятор с ассемблерными вставками глючит (компилит глючный код но без ассемблера его оптимизатор на высоте (а с ассемблером оптимизатор не важен, поэтому достаточно и MSVC).
?
что-то меня этот leave настораживает (хоть это и оффтоп)
а то, что до рола не оптимайзят ничего удивительного - тупые все компиляторы.
1) MSVC - оптимизация по скорости, GCC -O3. VC выигрывает > 15%
2) MSVC тот же, GCC -O3 -unroll-loops. VC выигрывает ~3%
3) MSVC отрубаем отладочную информацию, GCC тот же. VC выигрывает ~4%
4) MSVC тот же, GCC -O3 -unroll-loops -march=athlon-xp. GCC выигрывает ~1%
Но! Это под консолью, в gnome GCC выигрывает ~0.5%, в kde паритет, при том что в виндах висят антивиры, файрволы и т.п. + нет оптимизации под AXP.
Послушай, тебе ведь и примеры приводили, что нынешние микрософтовские компиляторы оптимизируют лучше чем gcc. У меня был крайний случай - математика, чистая скорость. Картина вышла такая:Во-первых до этого мне никто никаких примеров не приводил, а только делали пустые заявления в духе "GCC оптимизирует хуже чем MSVC" не удосуживаясь даже версию того и другого привести (на пример с "switch" я отвечал детально). Я при этом спрашивал версии, все молчали.
1) MSVC - оптимизация по скорости, GCC -O3. VC выигрывает > 15%
2) MSVC тот же, GCC -O3 -unroll-loops. VC выигрывает ~3%
3) MSVC отрубаем отладочную информацию, GCC тот же. VC выигрывает ~4%
4) MSVC тот же, GCC -O3 -unroll-loops -march=athlon-xp. GCC выигрывает ~1%
Но! Это под консолью, в gnome GCC выигрывает ~0.5%, в kde паритет, при том что в виндах висят антивиры, файрволы и т.п. + нет оптимизации под AXP.
Во-вторых: Как это вообще возможно сравнивать производительности программ, работающих в разных ОС под неизвестным окружением и приводить потом это в качестве аргумента о качественности оптимизации? Вам не пришло в голову откомпилить консольную прогу при помощи GCC под винду и сравнивать с компиляцией той же проги при помощи MSVC отрубив предварительно всё лишнее и выставив этим прогам максимальный приоритет? Мне вот пришло.
В третьих: Когда вы приводите такую статистику, необходимо писать ВЕРСИИ всех компиляторов. Например разные версии GCC очень отличаются по качеству оптимизации. Неужели не ясно что надо версии писать? (опции вы написали, что не может не радовать, первый из тех кто делал подобные заявления)
Я просто констатирую, что MSVC6 сосет по оптимизации у GCC-2.95.3 или GCC-4.0 или GCC-3.4.
Я это проверял на двух разных задачах (консольными приложениями в текстовом, а не оконном режиме которые очень требовательны к ресурсам проца (тоже чистые вычисления: в одном из сравнений арифметика длинных чисел, в другом - блочное шифрование в одинаковом окружении под виндой с Realtime приоритетом под админом и с отрубленой сеткой.
Про MSVC7/8 я ничего не говорил вообще, насчет них еще проверю.
PS: в GCC еще полезно иногда добавлять опцию -fomit-frame-pointer (это иногда может дать, существенное преимущество, а может и наоборот).
gcc --versiongcc 3.2.2
Послушай, тебе ведь и примеры приводили, что нынешние микрософтовские компиляторы оптимизируют лучше чем gcc. У меня был крайний случай - математика, чистая скорость.А твоя программа не использовала математическую библиотеку?
Этож учебная. Использовала только math.h, ничем другим пользоваться нельзя.
Нужно подробно объяснять, что ты протестировал не компиляторы?
странно, если бы было обратное
ms vc6 - уже лет 10 как на днях будет.
ms vc6 - уже лет 10 как на днях будет.Зато он стабильнее, чем MSVC7
не замечал
скорее - наоборот, у MSVC 6 - компилятор постоянно дохнет на сложном C++.
но я с появлением 7-ой версии отошел от активного использования плюсов
Объясняй, я весь внимание
Приложения собранные MS VC и gcc с GNU окружением используют различные математические библиотеки. Объявления из math.h - это не часть языка, а хидеры этой самой библиотеки.
А что, для компиляции выражения j = i + 1 или for(int i = 0; i < n; i++) result += a[i] * b[i] используются математические библиотеки?
Или в math.h есть существенно более интересные вещи, чем "#define Max(a, b) a)>(b?(a):(b" ?
Эээ, тригонометрия всяческая?
Разве что.
Или в math.h есть существенно более интересные вещи, чем "#define Max(a, b) a)>(b?(a):(b" ?да, там все существенно более интересно, особенно согласно стандарту C99
А такого макроса как ты написал там в принципе быть не может, поскольку он не безопасен для использования. Надеюсь не надо объяснять почему.
Ну, если a и b без сайд эффектов, то макрос вполне безопасный.
Ну, если a и b без сайд эффектов, то макрос вполне безопасный.разумеется, но любая функция стандартной библиотеки конечно же не может делать предположений относительно того есть ли у параметров side effects, за исключением assert (что в стандарте особо оговорено).
Т.е. любая функция кроме assert должна себя вести как функция (т.е. возможность side effects должна быть учтена хотя некоторые из них допустимо реализовать как макрос.
Читай тред внимательнее.
Читай math.h
Я из math.h использовал толькл sqrt и общее время исполнения этого sqrt заняло не более 0.01сек. из 32
использовал только sqrtТем более что sqrt компилируется в одну ассемблерную инструкцию, а если компилятор этого не может, то нечего пинять на math.h Кстати я склонен считать math.h и прочие библиотеки частью компилятора, особенно если речь идето сравнении производительности компиляторов.
тригонометрия всяческая?Большинство тригономестрических функций тоже компилируются в одну ассемблерную инструкцию.
Тем более что sqrt компилируется в одну ассемблерную инструкцию, а если компилятор этого не может, то нечего пинять на math.h Кстати я склонен считать math.h и прочие библиотеки частью компилятора, особенно если речь идето сравнении производительности компиляторов.Вот человек тебе скажет, что использовал gcc. О какой математической библиотеке ты подумаешь?
Оставить комментарий
kentavr
Может ли такое выражение изменить значение флага CF?for(int i=0;i<10;i++)
{
// что-то вроде __asm rcl tralala[i],1
// ....
}