mein Я не встречался со случаями когда break выглядит красивее. А ты Delphi знаешь? Скажи процедура XXX.close или XXX.free , это тоже аналоги Break?
А по поводу слишком длинного кода в условии: если время не критично, то в случае длинного кода можно использовать функции. Хотя я часто намеренно удлиняю код для ускорения (часто время выполнения очень критично), в общем когда цикл нужно ускорить я использую такую фишку:
Было:
for (100 раз например)
begin
xxx;
yyy;
...
end.
для ускорения:
for (50 раз)
begin
xxx;
yyy;
...
xxx;
yyy;
...
end;
При ипользовании такой фишки цикл может ускориться на 30-70%, можно и еще длиннее код делать, но как говориться все в меру! я больше 10 копий кода за одну итерацию еще ниразу не применял, так же как и goto, break.
Ой, вру, goto применял, когда писал на Fortran 77 но там деваться некуда!
Advanced member
Статус: Не в сети Регистрация: 09.03.2004 Откуда: Кишинёв
Silver_Clash Дельфи к сожалению не знаю(или к счастью ). Поэтому ничего сказать не могу.
Цитата:
Я не встречался со случаями когда break выглядит красивее
Да мне слово "break" просто нравится да и коротко, а как гласит известная поговорка ...
А из твоего примера я ничего не понял - ну ты и раставил эти операторы.
Да не покарают меня модераторы за ОФФТОП но просветить людей надо.
mein Объясняю: Как правил оператор цикла отнимает гораздо больше процессорного времени чем другие операторы.
Если число циклов сократить например в 2 раза за счет удвоения кода внутри цикла, прирост скорости должен быть существенным (30-70%). То есть получается число итераций сокращаем в двое, а внутри цикла два раза пишем одно и то-же, т.е. как-бы 2 итерации, если можно сказать старого образца, умещаются в одной итерации нового образца.
Уменьшать количество итерациё можно и более чем в 2 раза, но я более чем в 10 раз не применял, так как при дальнейшем уменьшении числа итераций прироста скорости я не замечал.
Advanced member
Статус: Не в сети Регистрация: 09.03.2004 Откуда: Кишинёв
Silver_Clash
Цитата:
Если число циклов сократить например в 2 раза за счет удвоения кода внутри цикла, прирост скорости должен быть существенным (30-70%). То есть получается число итераций сокращаем в двое, а внутри цикла два раза пишем одно и то-же, т.е. как-бы 2 итерации, если можно сказать старого образца, умещаются в одной итерации нового образца.
Идея понятна, но я думаю процент прироста скорости будет сильно падать с усложнением операций внутри цикла. Дело в лишних вызовах jmp, а может кривая реализация компилятора. Если первое, то два такта(а может и один) не столь критичны для сегодняшних камней.
Ray Adams
Цитата:
Использование break и continue считаю вполне нормальным
Вот и за меня заступились Сёдня писал некое подобие switch(){} для PIC'а(микроконтроллер) на асме - вот это изврат: goto каждую вторую третью команду идут .
Member
Статус: Не в сети Регистрация: 02.05.2004 Откуда: Tver
Все гораздо проще. Проверено практикой большим количеством неудачных программных проектов что мозг человека плохо разбирается с алгоритмом, который содержит много GOTO. Если без него не обойтись ( например текст сильно разбухает если эмулировать исключительные ситуации во вложенных циклах с помощью вспомогательных флагов и условий) то гораздо лучше быстрее и безопасней отправлять всех по GOTO. Важно не перестараться и помнить об "операторных скобках", например освобождать заказаную память или возвращать аппаратные биты в нужное состояние так как с GOTO поток команд не так очевиден.
По поводу "раскрытия цикла" не все так однозначно. Оптимизирующие компиляторы ( практически все ) часто сами используют этот трюк без вашего ведома. Припоминается знаменитейший в свое время Scaler Carmark'a тот что позволил добиться супер скорости Wolfenshtein 3D. Но например начитая с Dooom Кармарк сам его ограничил так как была потеря скорости из за слишком частой загрузки строк кеша команд в i486. А после Pentium Pro вообще невозможно предсказать как процессор будет переставлять команды. Это я к тому что сейчас все же лучше не забивать себе голову трюками и отдать это на откуп оптимизатору.
Member
Статус: Не в сети Регистрация: 15.04.2004 Откуда: Москва
stacq Silver_Clash Разворот цикла дает перимущества только в том случае, если xxxx и yyyy являются операторами доступа к памяти.
Если это функции, или обращения к свойствам класса, то никакого прироста производительности не будет.
Проверено, для Cel Tualatin оптимальным является разворот цикла в 8 раз. И еще, для ускорения доступа к памяти старайся не создавать объекты размером больше размера страницы. И конечно, выравнивание.
Member
Статус: Не в сети Регистрация: 15.04.2004 Откуда: Москва
S.Q.Lapp break - это je (jg и т.д.) вперед, continue - je назад .
Предсказатель ветвления в PIII и выше работает по следующему алгоритму - "вперед практиски всегда, назад практически никогда".
Если continue случается меньше в 10% цикла, то на производительность не влияет.
Хуже break. Его лучше заменять на изменение счетчика на верхний предел (не пройдет в Delphi для цикла for, но потянет mov ebx,верхний предел) и continue.
Страшнее оптимизируется кусок типа
while i > 0 do try
....
finally
Dec(i)
end;
И еще. Delphi (5) счетчик цикла размещает в EBX, поэтому циклы получаются не очень оптимальные (счетчик в ECX и использование LOOP эффективнее).
несколько своих замечаний:
2 mein
конструкции вида while(1) IMHO аналогичны loopforever: {... } goto loopforever.
***
switch-case-brake, наверное, действительно, оправдывает слово break. и только тут. использовать его в циклах(aka while(1)) не стоит - можно обойтись
asize - размер в байтах
length - в битах ( ( length >> 3 ) <= asize )
char bfld[asize] - array itself
int bitfield :: operator == ( const bitfield& bf ) const
{
unsigned int i;
int res = 1; //true result
if ( length == bf.length )
//looks for unequal bytes and terminates
for ( i = 0; i < asize && res; i++ )
res = btfld[i] == bf.btfld[i]; //if one isfound
else
res = 0;
return res;
}
***
2 IliaV
конструкция switch-case-brake не позволяет делать сложные проверки.
(bc3.1 help: case <constant expression>: where constant expression must be an int...) для уменьшения громоздкости можно хорошо выровнять текст:
if () statment0;
else if () statement1;
else if () statement2;
....
else statementN;
***
при написании оптимизированного кода goto бывает очень полезен.
C другой стороны, goto-путаница возникает из-за того, что непонятно откуда перешло управление на метку...
PS: Поделитесь с общественностью, кто знает ссылки на серьезные работы на тему.
PSPS: маленькая очепятка в начале темы (испр.) "...не знаю куда."
Advanced member
Статус: Не в сети Регистрация: 09.03.2004 Откуда: Кишинёв
Dilon Твой вариант понятен и мамонту - это плюс, но это же тот же самый иф-элс(просто запись укороченаяя), а после компила получится нечто большое и неоптимизированное всё равно.
S.Q.Lapp
Цитата:
В итоге заменил на
Код:
i = i ^ 3;
Причем числа могут быть произвольными, а не только 1 и 2. Красота. Читабельность, правда, нулевая. Зато скорость .
Вот это действительно красиво. Только я даже не знаю что за оператор "^". С ходу придумал два своих варианта:
Код:
i=(!(--i))+1;
или
Код:
i=(i&1)+1;
Реализация на асме этого дела не должна быть большой. Последнего например:
Код:
and ax,1 inc ax
. Выполнятся должно быстро по идее. Но читабельность опять же не каждый найдёт.
Advanced member
Статус: Не в сети Регистрация: 09.03.2004 Откуда: Кишинёв
Вот ломал голову(больную ) пол дня - так и не решил. В общем нужно менять(toggle) один бит в слове не трогая остальные биты. Я щас делаю деревянно:
если нужный бит=1 то очищаем его иначе ставим 1. На асме(для моего микроконтроллера) выглядит так:
Код:
LDP #PBDATDIR>>7 ; переход на страницу BIT PBDATDIR,BIT5 ; типа test LACL PBDATDIR ; загружаем в аккумулятор регистр BCND _NULL_BIT_,TC ; проверяем результат тестирования бита OR #0000000000010000b ; выставляем нужный бит 1 SACL PBDATDIR ; загоняем обратно в регистр B _EXIT_TEST_ ; убегаем отседова _NULL_BIT_ ; AND #1111111111101111b ; SACL PBDATDIR ;... _EXIT_TEST_
Так вот эта вся байда меня не очень устраивает(длинно, некрасиво и с прыжками) - хотел чёто пооптимизированнее придумать да ничё не пришло в голову. Есть в наличии такие команды: AND,OR,XOR,ROL,SFL. Может есть какойто линейный алгоритмик в несколько логических команд делающий это дело?
Member
Статус: Не в сети Регистрация: 11.11.2004 Откуда: Челябинск
mein Если сделать XOR операнда с числом, у которого нужный бит = 1, то этот бит операнда проинвертируется. Вроде так всегда было... А что за микроконтроллер?
Вроде так, хотя я этот ассемблер не знаю
LDP #PBDATDIR>>7 ; переход на страницу
LACL PBDATDIR ; загружаем в аккумулятор регистр
XOR #0000000000010000b ; инвертируем нужный бит
SACL PBDATDIR ; загоняем обратно в регистр
_________________ пишу я программу... и вдруг на клавиатуру выползает bug, буквально
Advanced member
Статус: Не в сети Регистрация: 09.03.2004 Откуда: Кишинёв
Rius Не, не получится: например если в нулевом бите был ноль то после операции получим единицу, что не гуд. Вот если если бы сначала загнать в аккумул-р регистр, потом его инвертнуть, потом выставить единицу в нужном месте, то тогда xor по идее должен сработать. Но как инвертнуть...
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения