вопрос по С++

Модератор: Злобный

Аватара пользователя
sadman
Завсегдатай
Сообщения: 2001
Зарегистрирован: Чт дек 15, 2005 23:46
Откуда: с ботаники
Контактная информация:

Сообщение sadman »

dmitriid,
dmitriid писал(а):эмуляция goto
Ничё подобного! goto - оператор безусловного перехода, который изменяет порядок выполнения программы при помощи передачи управления на оператор помеченый меткой!
В коде привидённом мной - ничё подобного не просиходит! Да, результат тот-же, но реализация радикально другая!

[off]добавлено спустя 5 минут:[/off]
keisik писал(а): sadman, имхо, вариант тоже не очень
Почему?
keisik писал(а): а если уж нельзя - то завести флажок на продолжение циклов и проверять его тоже
Хм... не уверен что правильно тебя понял, но если ты о том о чём я подумал, типа этого

Код: Выделить всё

flag = true;
for(i=0; i<50; i++) 
{ 
  for(j=0; j<100; j++) 
  { 
     ...... 
     if(cond()){flag=false; break; } 
     ...... 
  } 
  if(!flag)break;
}
То, имхо, лишняя работа и строчки кода, + куча ненужных переменных, логических.
Аватара пользователя
dmitriid
Новичок
Сообщения: 28
Зарегистрирован: Пн ноя 06, 2006 17:16
Контактная информация:

Сообщение dmitriid »

Ничё подобного! goto - оператор безусловного перехода, который изменяет порядок выполнения программы при помощи передачи управления на оператор помеченый меткой!
В коде привидённом мной - ничё подобного не просиходит! Да, результат тот-же, но реализация радикально другая!
Умный компилятор скорее всего сведет оба кода к одинаковым ассемблерным конструкциям :)

Вдобавок такое присваивание значений двум переменным можно приравнять к хаку, потому что поведение программы сложно проследить. Вирт (это который Паскаль придумал) такой выход (и выход с флагами) тоже к goto приравнивал, и правильно, имхо :)

В любом случае выход из вложенных циклов - это goto, явно заданный или эмулируемый :)

Не бойтесь goto :) Есть (весьма) малое количество случаев, где он оправдан
Аватара пользователя
keisik
Юзер
Сообщения: 197
Зарегистрирован: Вс фев 26, 2006 23:29

Сообщение keisik »

sadman
Почему?
Потому, что читать неудобно. Циклы с граничными условиями 100, 50 и явно числовыми значениями встречаются достаточно редко, поэтому придётся приравнивать каким-либо переменным.
Я имел в виду нечто подобное:

Код: Выделить всё

bool fContinue = true;
for (....; check some condition && fContinue; ...)
{
    for (....; check another condition && fContinue; ...)
    {
        if (IsEnough()) { fContinue = false; }
    }
}
Но опять же, это в крайнем случае, повторюсь, имхо лучший вариант - if (IsEnough()) { return; }

А вообще, dmitriid совершенно праав, просто в голове сидит навязчивая мысль, вдолбленная годами - goto это плохо, goto это очень плохо, goto это ужасно плохо. :) В принципе, даже где-то высказываение такое читал, что-то вроде "хороший программист не побоится использовать goto там, где это действительно нужно" ;)
Аватара пользователя
sadman
Завсегдатай
Сообщения: 2001
Зарегистрирован: Чт дек 15, 2005 23:46
Откуда: с ботаники
Контактная информация:

Сообщение sadman »

dmitriid писал(а):потому что поведение программы сложно проследить
это почему?
Умный компилятор скорее всего сведет оба кода к одинаковым ассемблерным конструкциям
Я говорил немного о другом! Если вам известно об архитектуре процессоров Intel (не знаю точно как там у AMD), так у этих процессоров есть конвейеры. На эти конвейеры "загружаются" операции, кот-рые возможно будут иметь место, т.е. процессор (или чё-то там связаное с ним) пытается предугадать на несколько шагов вперёд что будет происходить, для того что-бы сэкономить время при выполнении.
Когда ты нарушаешь ход выполнения программы оперетором goto, процессор никак не можут этого предугадать, и ему приходится выгружать из конвейерной очереди всё что было загружено туда, и соответственно происходит потеря времени! Т.е. при использовании goto обязательно произойдёт выгрузка операций из конвейера.
[off]зы надеюсь всё понятно объяснил :)[/off]

[off]добавлено спустя 2 минуты:[/off]
keisik писал(а): имхо лучший вариант - if (IsEnough()) { return; }
просто это не всегда верный выход, т.к. наверняка после этих циклов есть ещё что-то, что должно выполняться, несмотря на то закончилось выполнение циклов нормально и "насильно"

[off]добавлено спустя 1 минуту:[/off]

keisik,dmitriid,
но по большому счёту, каждый пишет код так как ему удобно.
Просто эта история о конвейерах, о которой я узнал относительно недавно, заставила меня задуматься...
Аватара пользователя
dmitriid
Новичок
Сообщения: 28
Зарегистрирован: Пн ноя 06, 2006 17:16
Контактная информация:

Сообщение dmitriid »

sadman писал(а):Просто эта история о конвейерах, о которой я узнал относительно недавно, заставила меня задуматься...
Лучше не задумываться :) Это абсолютно ненужная микрооптимизация. В большинстве (тривиальных) случаев компилятор развернет цикл в один и тот же код, в котором, возможно, даже не будет goto :)

Выгрузка операций из конвеера займет сколько? Один такт процессора. Два? Это сильно отразится на программе? Только в случае, если пишется программа с реальным временем отклика. Но тогда она даже не под винду писаться будет и не под линукс ;)

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

Например (не совсем о goto, но все же :) )

Код: Выделить всё

int k = 0;
for(k=0; k <10; k++)
{
}
Этот код майкрософтовский компилятор легко преобразовывает в:

Код: Выделить всё

k = 10;
Предусмотреть такое очень сложно, особенно если случаи нетривиальны.

Так что во вложенных циклах случай с флагами или присваиванием переменным значения абсолютно идентичен случаю с goto, потому что компилятор возможно сводит все к goto. А возможно избавляется от goto.

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

Кстати, многие парсеры и, емнип, конечные автоматы легче писать с goto. Автоматические парсеры/лексеры все равно порождают код с goto (например). Так что не надо goto обижать. Оно иногда хорошее :)
Аватара пользователя
sadman
Завсегдатай
Сообщения: 2001
Зарегистрирован: Чт дек 15, 2005 23:46
Откуда: с ботаники
Контактная информация:

Сообщение sadman »

dmitriid писал(а):Выгрузка операций из конвеера займет сколько? Один такт процессора. Два? Это сильно отразится на программе?
dmitriid писал(а):В прикладных приложениях задумываться о том, что процессору придется очищать очередь по меньшей мере глупо
Ну тут я не спорю. НО! В большой, реальной большой и сложной программе, злоупотребление goto может значительно понизить читабельность. Хотя, это не главное, опять-же - если тебе удобно читать такой код - пожалуйста, никто не запрещает. Но в той-же реальной большой и сложной программе выгрузка операций из конвеера может оказаться дорогим удовольствием.
Но, если ты всегда писал маленькие програмки и не задумывался об этой, как ты говоришь "ненужной микрооптимизации", то тебе будет трудно оптимизировать код в большом проекте.
Именно поэтому я и пытаюсь научиться писать оптимизированый код. Пусть в моих маленьких прогах он мне сэкономит сотые доли секунды, зато при написании большой программы я не буду задумываться о том почему так меленно всё работает.вот. :)
Аватара пользователя
dmitriid
Новичок
Сообщения: 28
Зарегистрирован: Пн ноя 06, 2006 17:16
Контактная информация:

Сообщение dmitriid »

sadman писал(а):Именно поэтому я и пытаюсь научиться писать оптимизированый код. Пусть в моих маленьких прогах он мне сэкономит сотые доли секунды, зато при написании большой программы я не буду задумываться о том почему так меленно всё работает.вот.

В первую очередь надо оптимизировать алгоритмы. Они могут дать выигрыш в производительности в десятки раз. В то время, как ассемблерная оптимизация может дать прирост ну в два, в три раза - и то в вырожденных ситуациях (типа оптимизация под SSE, 3DNow! и т.п.)

Если программа торомзит, то она скорее тормозит не из-за конвеера, а из-за алгоритма. Даже если новый алгоритм требует очистки конвеера каждую вторую операцию, он все равно может дать выигрыш в производительности за счет, например, отказа от копирования объектов в пользу передачи ссылок на них ;)

Как я уже сказал, goto можно применять реально в очень маленьком количестве случаев, потому что использование goto чаще засоряет код. Но вот для выхода из вложенных циклов ничего умнее goto пока не придумано :)
Аватара пользователя
keisik
Юзер
Сообщения: 197
Зарегистрирован: Вс фев 26, 2006 23:29

Сообщение keisik »

sadman, на самом деле, сброс конвейера не такая уж страшная штука. Более, того, чтобы представить себе, насколько часто это происходит, можешь подсчитать, к примеру количество if-ов даже в каком-нибудь маленьком проекте. А каждый участок вроде

Код: Выделить всё

if (CheckSomeСondition())
{
    Foo();
}
else
{
    Bar();
}
- это, в принципе, 50%-ая вероятность что "механизм предсказания переходов" ошибётся. Так что не стоит слишком на этом заострять внимание, как и вообще на излишней и ранней оптимизации. Ранняя оптимизация, и "микрооптимизация" вообще - суть зло, на самом деле. Оптимизируй структуры данных и алгоритмы, а такого уровня вещи оставь компилятору, ибо он в них шарит всяко получше, чем все мы тут вместе взятые ;)
[off]У процессоров AMD, кстати, конвейер, естественно, тоже есть, причём он ощутимо короче, чем в Интеловских процессорах, так что там всё ещё менее трагично ;)[/off]
просто это не всегда верный выход, т.к. наверняка после этих циклов есть ещё что-то, что должно выполняться
- дык ведь код-то твой ;) Напиши так, чтобы не было - вынеси циклы в отдельный метод. имхо, опять же, т.е. я бы так постарался сделать. :)
Аватара пользователя
kubinets
Продвинутый
Сообщения: 401
Зарегистрирован: Чт авг 03, 2006 00:21

Сообщение kubinets »

=MIA= писал(а):по нажатию двух пробелов
А где второй пробел-то взять?! ;)
Аватара пользователя
=MIA=
Отец
Сообщения: 4635
Зарегистрирован: Сб июл 02, 2005 15:25
Откуда: Кишинев
Контактная информация:

Сообщение =MIA= »

[off]kubinets,
проехали уже...см. дату темы[/off]
Аватара пользователя
Злобный
Завсегдатай
Сообщения: 2716
Зарегистрирован: Сб июн 18, 2005 21:05
Контактная информация:

Сообщение Злобный »

dmitriid писал(а):Как я уже сказал, goto можно применять реально в очень маленьком количестве случаев, потому что использование goto чаще засоряет код. Но вот для выхода из вложенных циклов ничего умнее goto пока не придумано :)
[off]Явного применение goto очень советуют избегать. Все. Я никогда в своей жизни не видел рекомендации к явному использованию goto. Для ситуации описанной тобой (выход из вложенного цикла) некоторые языки имеют решение. Скажем, в Java есть возможность маркировать блоки кода метками и, делая break <метка>, указывать из какого именно блока кода ты намерен выйти (неявный goto). В дотнете пока ничего подобного не нашел, но и они это сделают. В любом случае, явное употребление goto подавляющим большинством программистов считается, по меньшей мере, дурным тоном.[/off]
Аватара пользователя
sadman
Завсегдатай
Сообщения: 2001
Зарегистрирован: Чт дек 15, 2005 23:46
Откуда: с ботаники
Контактная информация:

Сообщение sadman »

Злобный,
ну мы тут обсуждали как в с++ выйти из циклов, и использовать-ли goto
явное употребление goto подавляющим большинством программистов считается, по меньшей мере, дурным тоном
ну а это ни для кого не секрет ;)
хотя, как видно, есть и те что считают что goto - это ничё страшного.
зы кому интересно - в инете полно статей о ГоТо и о том как и почему его "забраковали". Где-то читал что его даже следует Полностью ИСКЛЮЧАТЬ из языков
Аватара пользователя
Злобный
Завсегдатай
Сообщения: 2716
Зарегистрирован: Сб июн 18, 2005 21:05
Контактная информация:

Сообщение Злобный »

Сэдмэн писал(а):ну мы тут обсуждали как в с++ выйти из циклов, и использовать-ли goto
[off]Ага, потому я сереньким все и закрасил. :)[/off]
dmn
Юзер
Сообщения: 177
Зарегистрирован: Вт мар 01, 2005 22:25

Сообщение dmn »

sadman писал(а): Я говорил немного о другом! Если вам известно об архитектуре процессоров Intel (не знаю точно как там у AMD), так у этих процессоров есть конвейеры. На эти конвейеры "загружаются" операции, кот-рые возможно будут иметь место, т.е. процессор (или чё-то там связаное с ним) пытается предугадать на несколько шагов вперёд что будет происходить, для того что-бы сэкономить время при выполнении.
Когда ты нарушаешь ход выполнения программы оперетором goto, процессор никак не можут этого предугадать, и ему приходится выгружать из конвейерной очереди всё что было загружено туда, и соответственно происходит потеря времени! Т.е. при использовании goto обязательно произойдёт выгрузка операций из конвейера.
зы надеюсь всё понятно объяснил
:?
А я то, дурак, думал что выгрузка конвеера происходит при JMP, LOOP, CALL, RET, ENTER, LEAVE, INT, IRET и BOUND командах. Теперь буду знать что оптимизацию бинарного кода программы можно осушествить на уровне высокого языка программирования.
Аватара пользователя
sadman
Завсегдатай
Сообщения: 2001
Зарегистрирован: Чт дек 15, 2005 23:46
Откуда: с ботаники
Контактная информация:

Сообщение sadman »

dmn,
вероятно, это следует воспринимать как иронию...
Я говорю о том, что мне рассказал препод по фортрану! Я не знаю в каких случаях происходит выгрузка! Но я знаю что на уровне высокого языка можно оптимизировать код таким образом что-бы приложение работало быстрее и потребляло меньше ресурсов
dmn
Юзер
Сообщения: 177
Зарегистрирован: Вт мар 01, 2005 22:25

Сообщение dmn »

sadman,
[off]Все мои познания по ФОРТРАНУ сводятся к тому что это первый язык высокого уровня (ЦПУ независимый). В курсах по изучению любого языка высокого уровня врядли должны встречатся такие слова как: Intel, конвейеры, процессор и.т.д.[/off]
Аватара пользователя
dmitriid
Новичок
Сообщения: 28
Зарегистрирован: Пн ноя 06, 2006 17:16
Контактная информация:

Сообщение dmitriid »

Злобный писал(а): Явного применение goto очень советуют избегать. Все. Я никогда в своей жизни не видел рекомендации к явному использованию goto. Для ситуации описанной тобой (выход из вложенного цикла) некоторые языки имеют решение. Скажем, в Java есть возможность маркировать блоки кода метками и, делая break <метка>, указывать из какого именно блока кода ты намерен выйти (неявный goto). В дотнете пока ничего подобного не нашел, но и они это сделают. В любом случае, явное употребление goto подавляющим большинством программистов считается, по меньшей мере, дурным тоном.
И вот теперь скажи мне, чем break с меткой отличается от goto с меткой ;)

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

ЗЫ. Я ж не призываю использовать goto повсеместно ;)
В курсах по изучению любого языка высокого уровня врядли должны встречатся такие слова как: Intel, конвейеры, процессор и.т.д.
+100

Разверните-ка мне следующее в машинный код :lol: :

Код: Выделить всё

/*
    Javascript, но идея должна быть понятна
*/

function map(F, Arr)
{
    for(i = 0; i < Arr.length; i++)
    {
        F(Arr[i]);
    }
}


function func()
{
    map(
        function(X)
        {
            alert(X * X);
        },
        [1, 2, 3]
    )
}
;)
Аватара пользователя
sadman
Завсегдатай
Сообщения: 2001
Зарегистрирован: Чт дек 15, 2005 23:46
Откуда: с ботаники
Контактная информация:

Сообщение sadman »

dmn писал(а):sadman,
Все мои познания по ФОРТРАНУ сводятся к тому что это первый язык высокого уровня (ЦПУ независимый). В курсах по изучению любого языка высокого уровня врядли должны встречатся такие слова как: Intel, конвейеры, процессор и.т.д.
Причём тут должны-не_должны??? :?
Я тебе говорю что препод об этом рассказывал! Т.к. в самом начале изучения фортрана нам рассказывали общие сведения, в том и числе и немного об архитектуре процессоров.
[off]зы и эт, давай перестанем флудить, ок? Если есть чё по теме - выкладывай. А говорить что в каких курсах ДОЛЖНО преподаваться будем в другой теме[/off]
Ответить

Вернуться в «Программирование»