(решено) GoTo или repeat until?

Форум для изучающих FPC и их учителей.

Модератор: Модераторы

Re: (решено) GoTo или repeat until?

Сообщение vitaly_l » 07.09.2015 17:49:57

скалогрыз писал(а):о! так ты ассемблер знаешь!

Ну... это громко сказано, но я его(ассемблер) с трудом понимаю.

скалогрыз писал(а):код в целом идентичен, кроме дополнительной jmp инструкции (собственно самого goto)

Честно говоря я думал, что они либо равны, либо наоборот...
Прыжок GoTo - это jmp 14... завершение 16...
jl - это второе сравнение и оно обходит 16 выход...
но откуда оно(jl) появилось, я не понимаю? :| :oops: :cry:

Подать электричество на северный полюс, для белых медведей - было много проще... чем ассемблер...

А зачем вообще этот jl там нужен??? Откуда он взялся?
Смотрим на repeat... ага там в ASM указано на если равно (je)...

Так там разные условия поставлены...
Шарлотан! Хитрый, лис... художников в заблуждение, хотел ввести...
А как такую же конструкцию ассемблера сделать при помощи GoTo? Или это технически не реально?

А вот так?
Код: Выделить всё

  i:=1;
  loop:     
    if i=10 then goto lebelStop;
    inc(i);
    goto loop;
    lebelStop:



.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: (решено) GoTo или repeat until?

Сообщение скалогрыз » 07.09.2015 18:36:18

vitaly_l писал(а):Так там разные условия поставлены...
Шарлотан! Хитрый, лис... художников в заблуждение, хотел ввести...

в данном случае, условия (равно или меньше) на кол-во инструкций не повлияют.

vitaly_l писал(а):А как такую же конструкцию ассемблера сделать при помощи GoTo? Или это технически не реально?

Вообще-то, то что ты показываешь, это цикл while, а не repeat until (т.к. проверка условия выполнимости у тебя сделена перед телом цикла, а не после), но в итоге инструкций стало ещё больше (благодаря дополнительному goto!).
Код: Выделить всё
; [27] i:=1;
      mov   word ptr [ebp-4],1
@@j21:
; [29] if i=10 then goto lebelStop;
      mov   ax,word ptr [ebp-4]
      cmp   ax,10
      je   @@j22
      jmp   @@j23
@@j22:
      jmp   @@j24
@@j23:
; [30] inc(i);
      inc   word ptr [ebp-4]
; [31] goto loop;
      jmp   @@j21
@@j24:
; [33] end;

Так что перепись на цикл while в данном случае, также вызове экономию инструкций.

Да чуть не забыл. Операторвы ветвления (if, case) и соответствующие циклы (while, repeat, for), все реализуются на основе инструкций условных переходов (je, jne, jl, jnl, jg... и т.д.). Так что можешь их считать как раз аппаратной поддержкой repeat...until ;)
Goto - же, это безусловный переход (jmp).
И в тех местах где ты его используешь вместе с каким-нибудь условием, например
Код: Выделить всё
if i=10 then goto ...

вместо цикла, то в любом случае, ты сначала делаешь проверку условия (какой-нить jxx.. + jmp, если условие на выпополнилось) а потом ещё и дополнительный jmp чтобы пойти по указанному месту.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: (решено) GoTo или repeat until?

Сообщение vitaly_l » 07.09.2015 18:44:11

скалогрыз писал(а):Вообще-то, то что ты показываешь, это цикл while


Может быть тогда хотя-бы так?
Или ASM конструкцию repeat until - невозможно построить с помощью GoTo?
Код: Выделить всё

  i:=1;
  loop:     
    if inc(i)=10 then goto lebelStop;   
    goto loop;
    lebelStop:

Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: (решено) GoTo или repeat until?

Сообщение скалогрыз » 07.09.2015 18:59:03

vitaly_l писал(а):Может быть тогда хотя-бы так?

ты просто выкинул тело цикла
Код: Выделить всё
inc(i)

для чего?
vitaly_l писал(а):Или ASM конструкцию repeat until - невозможно построить с помощью GoTo?

Asm-конструкции repeat..until не существует.
Есть условные переходы, которые перенесут исполнение к определённой инструкции, если условие выполнено.
Если условие не выполнено перейдут к следующей.
Т.к. компилятор знает, что условие проверяется в цикле, то прыжок к "определённой инструкции" всегд будет либо в начало тела цикла (while) либо из цикла (repeat).

С использование Goto, этот прыжок будет лишь на другую инструкцию прыжка, которая как раз приведёт либо в тело цикла либо из него.
Избыточные инструкции!

Добавлено спустя 5 минут 51 секунду:
ты можешь надеятся, что компилятор оптимизирует выражение
Код: Выделить всё
if i=10 the goto outofLoop;

как "если i = 10 иди на outofLoop",вместо
"если i = 10 иди на верное условие:
верное условие: иди на outofLoop"
Но, как я сказал раньше, наличие goto может как раз предостеречь компилятор от всячексих оптимизаций.
Что FPC и не делает :)

Добавлено спустя 2 минуты 4 секунды:
В конце-концов, даже при наличии оптимизаций "goto" будет лишь столь-же эффективен, как repeat..until но не быстрее.
А с точки зрения кода, так тебе придётся печатать даже больше, т.к. сначала нужно будет объявить "label" (придумать ему имя) и этот самый label потом расставить по коду ( и следить чтобы он был в правильном месте).
с точки зрения repeat ... until "бюрократии" меньше. Художники любят бюрократию?
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: (решено) GoTo или repeat until?

Сообщение vitaly_l » 07.09.2015 19:09:30

скалогрыз писал(а):для чего?

а вот это уже правильный вопрос.

Суть в том что, в изначальном вопросе, было про: либо два цикла, либо один цикл и GoTo... там ещё предлагали три цикла... вместо одного и GoTo.
Однако, чтобы проверить, надо полностью условие установить. B возможно, кстати, тогда в ASM - получится меньше ASM инструкций, т.к. меньше циклов.

А ВООБЩЕ задача (цель) - понять, как в коде априори избежать чтения кода на ASM, зная заведомо результат от полезного использования GoTo.


.
Последний раз редактировалось vitaly_l 07.09.2015 19:13:27, всего редактировалось 2 раз(а).
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: (решено) GoTo или repeat until?

Сообщение скалогрыз » 07.09.2015 19:12:00

vitaly_l писал(а):А ВООБЩЕ задача (цель) - понять, как в коде априори избежать чтения кода на ASM, зная заведомо результат от полезного использования GoTo

Обратись к моему первому посту ;)
Смысл каков - пиши с Goto! Просто пиши пиши пиши!
Наслаждайся! Но если ты придёшь к выводу, что код лучше будет переписать без goto! обязательно напиши здесь!
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: (решено) GoTo или repeat until?

Сообщение vitaly_l » 07.09.2015 19:20:17

скалогрыз писал(а):Но если ты придёшь к выводу, что код лучше будет переписать без goto! обязательно напиши здесь!

:arrow: :| :oops: :( :cry: нету в Вас искорки... никто не хочет защитить несчастного оператора: GoTo...
:arrow: все ополчились... :arrow: :| :oops: :( :cry: ну и ладно, злые Вы уйду я от Вас! :roll:

.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: (решено) GoTo или repeat until?

Сообщение скалогрыз » 07.09.2015 19:35:16

ну а почему не придумают "break" по лейблу?!

например:
Код: Выделить всё
  for i:=1 to list.Count-1 do label mainFor;
    for j:=2 to TItem(list[i]).dataCount-1 do 
      if data[j].isBad then break mainFor;

сий бряк приведёт к выходу из обоих циклов и "i" и "j".
тогда и goto не надо будет заводить для выхода из вложенных циклов.

а я не прав. Break процедура, а Goto выражение языка.

Добавлено спустя 7 минут 24 секунды:
vitaly_l писал(а):никто не хочет защитить несчастного оператора: GoTo...

Кнут хочет
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: (решено) GoTo или repeat until?

Сообщение vitaly_l » 07.09.2015 19:59:33

Кнут хочет
Пойду дружить с Кнутом! (я его естественно не читал).
Честно говоря я думал что, у программистов как в шахматах,
все стандартные партии давно уже расписаны. У Кнута так много томов...

Всем спасибо - глупые вопросы закончились, а умные вопросы ещё не придумал.
Отключаюсь, от обсуждения. Может как нить ещё загляну.



.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: (решено) GoTo или repeat until?

Сообщение Cheb » 10.09.2015 00:39:32

Используя goto - спускаешься вниз на ступеньку в уровне абстракции. Начинаешь мыслить не в системе понятий задач и алгоритмов, а в системе понятий машины этого, как его, фон Неймана. То есть, отказываешься от того, для чего языки высокого уровня и задумывались. Код, естественно, читается хуже -- поскольку требует склада ума, работающего, опять же, в системе понятий фоннеймановской машины. Что характерно далеко не для всех.

Откуда, goto - очень узкоспециализированный инструмент для ручного тюнинга узких мест в коде.
Поскольку мест таких в нормальном коде - 5%, а в 95% из них узким местом на самом деле является (не)дружественность структуры данных кешу процессора - соответственно, goto мне за последние лет пятнадцать ни разу не понадобился. Поскольку я давно адаптировал своё мышление к алгоритмической системе понятий, а на 5% потери скорости забил болт.

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

Для справки: разница между обращением к кешу и обращением к ОЗУ уже почти как разница между обращением к ОЗУ и обращением к диску. Латентность памяти, если мерить в наносекундах, упёрлась рогами в потолок уже десятилетие назад, и стех пор вообще не улучшается! Т.е. вынь да положь 5нс на чтение, 10нс на чтение-модификацию-запись. На фоне этого, ускорение алгоритмов от применения goto бодро стремится к нулю.

Второе применение goto, как уже упоминалось выше - костыль для всяких редких случаев, типа прискорбного отсутствия в Паскале вещей типа Break(2).

Добавлено спустя 7 минут 29 секунд:
З.Ы. Для примера: за то время, пока выполняется Inc(<некешированная переменная>) (10нс на очень хорошей ОЗУ), современный 3ГГц проц успевает тикнуть 30 раз. Даже если он тормозит, выполняя одну инструкцию за два такта - сами прикиньте сколько условных переходов он успеет выполнить (каюсь, детальные подробности этого забыл). Уж пара вызовов процедур точно должна уложиться.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34

Re: (решено) GoTo или repeat until?

Сообщение vitaly_l » 10.09.2015 13:42:54

Cheb писал(а):Опять же, по серьёзному такое утверждать с профайлингом в руках, но навскидку вызов процедуры, уже попавшей в кеш инструкций, по весу просто смехотворен в сравнении с чтением одного незакешированного байта из оперативной памяти.

Для справки: разница между обращением к кешу и обращением к ОЗУ уже почти как разница между обращением к ОЗУ и обращением к диску.

Для примера: за то время, пока выполняется Inc(<некешированная переменная>) (10нс на очень хорошей ОЗУ), современный 3ГГц проц успевает тикнуть 30 раз. Уж пара вызовов процедур точно должна уложиться.

Предъявленные Cheb заявления - приняты в НаиВысший холивар художников!

:?: Уважаемый Cheb, а как положить "всё" в кеш?
:arrow: Дайте, пожалуйста пример паскалевского кода закладки данных в кэш и последующего обращения к ним, чтобы можно было проанализировать.



.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: (решено) GoTo или repeat until?

Сообщение Лекс Айрин » 10.09.2015 14:27:15

vitaly_l, это аппаратная возможность. Максимум, что можно -- разрешить/запретить кеширование.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: (решено) GoTo или repeat until?

Сообщение Cheb » 10.09.2015 14:28:52

пример паскалевского кода закладки данных в кэш и последующего обращения к ним,

Для Паскаля и любых языков процессор - чёрный ящик. Мы лишь примерно представляем принципы его работы, но влиять на его решения можем лишь опосредованно.
Но опосредованно - не значит неэффективно.


Основной принцип, общий что для Паскаля. что для сиплюсплюс, туз- он и в Африке туз: чтение/запись памяти не должно скакать по всему адресному пространству. Желательно, чтобы данные по которым идёт активная работа располагались компактно в одной или нескольких областях памяти, влезающих в кеш первого уровня. А это - около 64 килобайт на все потоки всех процессов.

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

Строгое следование принципам ООП очень способствует дружественности к кешу, поскольку все данные компактно собраны в экземпляре класса. Переключение на работу с другим объектом как раз и будет стоить примерно одно-два-немножко обновлений кеша, поскольку между кешем и памятью данные перекачиваются кусками в точно не помню, ЕМНИП по 64 байта. В 32 бтном приложении класс, имеющий 15 полей типа Longint, полностью влезет в одну линейку кеша. Конечно, такие маленькие классы в реале редкость, но принцип остаётся.

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

Зло, это:
- глобальные переменные, когда их много и значительный объём данных храни в них, и/или когда в программе уйма модулей, хранящих данные в них
- хранение данных в нескольких массивах, допустим у тебя есть точки, и координаты x хранятся в одном, координаты y - в другом, а цвет - в третьем.
- глубокая рекурсия, когда вызовов столько, что локальные переменные уплывают из кеша.

Далее, на примере программной обработки картинки.
Если планируются операции типа блюра большого радиуса, то лучше хранить картинку не в двумерном массиве ширина х высота, а разбить её на квадратные куски весом не более 1..4 килобайт. Для 8 бит RGBA это будет 32х32. И тогда операцию блюра выполняешь не тупым проходом двумя циклами по х и y, а проходом по этим 32х32 чанкам, внутри которых уже по x и y. Для удобства понадобится чтение и запись пиксела завернуть в виртуальные методы (чтобы адресовать x, y к нужному чанку), но это всё равно быстрее.
Далее, если радиус блюра - огромный, типа 100, то внутри чанка тоже нельзя проходить по x, y. Надо проходить каждый из попадающих в радиус чанков по очереди. Для этого (чтобы не получить каку с округлением) можно завести локальную переменную - 16 или 32 битный буфер-аккумулятор, в который суммировать значения, собираемые с соседних чанков по одному чанку, а ужать до 8 бит и записать в свой чанк - в конце операции.

Я могу быть не прав насчёт такой структуры, но факт остаётся: при операциях "многие влияют на многие" надо елозить по памяти не как удобно, а чтобы елозилось по ограниченным её участкам, медленно смещаясь. Например, можно *не* разбивать на чанки, хранить картинку в двумерном массиве, но принципы обхода памяти циклами должны быть как если бы разбиение на чанки было. Не два вложенных цикла, а четыре, и т.п.

Добавлено спустя 15 минут 42 секунды:
З.Ы. Когда надо над многими объектами выполнить несколько операци, то:

Дружественно: o1.A(); o1.B(); o1.C(); o2.A(); o2.B(); o2.C(); ...

Недружественно: o1.A(); o2.A(); ... ;o1.B(); o2.B(); ... ; o1.C(); o2.C(); ...

Конечно, если операция B() зависит от результата A() не только своего, но и других объектов - то уже никуда не денешься, придётся делать недружественно.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34

Re: (решено) GoTo или repeat until?

Сообщение vitaly_l » 10.09.2015 14:57:02

Cheb писал(а):А это - около 64 килобайт на все потоки всех процессов.

многопоточность это миф, равно как и параллельные процессоры. Суть в более универсальном использовании ОДНОГО процессора(с 2-мя, 4-мя ядрами). Но ниточка расчётов, по прежнему остаётся ниточкой в самом процессоре и на самом деле все рассчёты В ПРОЦЕССОРЕ, независимо от кол-ва процессоров - не параллельны, а последовательны.
:arrow: Правильно? (вопрос странный, но в холиваре у художников, всегда нужно 100% уточнить все вводные)

Cheb писал(а):Я могу быть не прав насчёт такой структуры

Думаю, Вы можете оказаться очень правым, все навороченные программы по 3D - рендер, в новых фишечках, делают именно квадратами.
Размер квадратов, там, пользователю, можно менять... а с учётом Вашего описания, предположительно, в зависимости от памяти процессора.

Касаемо разбиения картинки или кода... Вкусный орешек! Спасибо! Но проверю - благо это просто, если это так, то оч. круто, хотя и усложняет немного код и видение программы человеком.

Лекс Айрин писал(а):это аппаратная возможность. Максимум, что можно -- разрешить/запретить кеширование.

Я правильно понимаю, что запретить кеширование сложно и оно всегда активно? Или я заблуждаюсь?

Cheb писал(а):все данные компактно собраны в экземпляре класса

Речь идет об этом классе: TSomeName = class ... end; <= Правильно? (вопрос странный, но в холиваре у художников, нужно 100% уточнить все вводные)
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: (решено) GoTo или repeat until?

Сообщение Лекс Айрин » 10.09.2015 15:47:09

vitaly_l писал(а):многопоточность это миф, равно как и параллельные процессоры.


Вы таки не правы. физическая многопоточность (параллельные процессоры) есть.... а вот пямять на них всех одна.

vitaly_l писал(а):Или я заблуждаюсь?


Именно заблуждаетесь. Я около года работал за компом с отключенными в BIOS кешами (кажется, 2 и 3го уровня). 98 форточки ставились около 4х часов, 2К офис не ставился вообще. Про запрет программный кеширования для первого уровня я тоже слышал, в документации интел. Если я правильно помню, это не операция процессора -- это воздействие на контроллер. Так что реальный смысл в сбросе кеша отсутствует...

Ах да... есть еще способ объявить кеш недостоверным... тогда он должен сбросится и заполнится заново. Но я его не помню.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Пред.След.

Вернуться в Обучение Free Pascal

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 14

Рейтинг@Mail.ru