LINUX.ORG.RU

Метапрограммирование - проблемы и пути их решения.

 , ,


12

6

Пичал я тут на днях токенайзел для C++-кода, но всё это меня добило я решил поделится.

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

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

Чтобы не быть голословным пишем что-то типа

constexpr uint64_t f(uint64_t a, uint64_t b) {
  return a + b; 
}
Всё ок, но пишем что-то сложнее, аля:

uint64_t m[] = {0, 1, 2, 3, 4};
constexpr uint64_t f(uint64_t a, uint64_t b) {
  return m[a] + m[b]; 
}

Бида( или это моё неосиляторство плюсов?), дак зачем они запилили эту фичу, если она может лишь галимую примитивщину? Шаблоны ещё ущербней. В чем приемущество? Зачем?

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

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

У меня есть 3 пути: терпеть, пилить свой язык и конпелятор самому( что долго и нудно) и ваш совет.

Ответ на: комментарий от AIv

Насчет разме^ра согласен, я вообще предлагаю ограничится N=1<<R.

вот тут не обязательно, может мне для оптимизации захочется взять N=8180 скажем?

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

если делать хорошо, то 5-6 строчек не хватит, поверь;-) У квадрата доп четыре ребра и четыре вершины - их надо обрабатывать отедльно. У куба 6 граней, 12 ребер и 8 вершин. Давай пока огранимся центральной областью.

Насчет читерства все просто. Есть числ схема, ее менять нельзя. Можно как угодно менять алгоритм (послед арифметич действий) при условии что в итоге реализуется та же самая схема.

AIv ★★★★★
()
Ответ на: комментарий от AIv

если делать хорошо, то 5-6 строчек не хватит, поверь;-)

не поверю:

data(0,0).tmp_u= /// 1-я
data(0,N-1).tmp_u= /// 2-я
for(int iy=1; iy<N-1; iy++) {
	data(0,iy).tmp_u= /// 3-я
	for(int ix=1; ix<N-1; ix++){ 
		long offset = ix+iy*N;
		data[offset].tmp_u = A*data[offset].u + 
			B*( data[offset-1].u + data[offset+1].u + data[offset-N].u + data[offset+N].u );
	}
	data(N-1,iy).tmp_u= /// 4-я
}
data(N-1,0).tmp_u= /// 5-я
data(N-1,N-1).tmp_u= /// 6-я

www_linux_org_ru ★★★★★
()
Последнее исправление: www_linux_org_ru (всего исправлений: 1)
Ответ на: комментарий от AIv

Да и с чего бы тебе таких странностей захотелось?;-)

швы продублировать

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от AIv

Насчет читерства все просто. Есть числ схема, ее менять нельзя. Можно как угодно менять алгоритм (послед арифметич действий) при условии что в итоге реализуется та же самая схема.

как-то мне это непонятно, тесно и не нравится — все это очень не в моем стиле

я признаю только условия вида «все знаки (или часть знаков) должны совпадать»

бег в мешках какой-то

фу короче

хотя над порядком обхода все же и интересно подумать

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

ну, два ребра ты уже потерял. А теперь подумай что будет для куба;-) Гранусловия роли не играют, надо брать самые простые.

Я че то непойму, ты с ТС-ом что ли по упертости соревнуешься?;-)

AIv ★★★★★
()
Ответ на: комментарий от AIv

ну, два ребра ты уже потерял

да, действительно

но все равно не поверю:

  for(int it=0; it<Ndrops*N; it++) {
    for(int iy=0; iy<N; iy++) {
      memcpy( &data(0,-1), &data(0,  0), N*sizeof(data(0,0)) );
      memcpy( &data(0, N), &data(0,N-1), N*sizeof(data(0,0)) );

      data(   0,iy).tmp_u = A*data(  0,iy).u + B*sum_of_data_u( (   0,iy),(   1,iy),(  0,iy-1),(  0,iy+1) );
      for(int ix=1; ix<N-1; ix++) {
        data(ix,iy).tmp_u = A*data( ix,iy).u + B*sum_of_data_u( (ix-1,iy),(ix+1,iy),( ix,iy-1),( ix,iy+1) );
      }
      data( N-1,iy).tmp_u = A*data(N-1,iy).u + B*sum_of_data_u( ( N-2,iy),( N-1,iy),(N-1,iy-1),(N-1,iy+1) );
    }
    for(int iy=0; iy<N; iy++) {
      for(int ix=0; ix<N; ix++) {
        data(ix,iy).u = data(ix,iy).tmp_u;
      }
    }
  }

в 5 строк если с макросом, и в 4 если развернуть (и размер массива д.б. N*(N+2))

А теперь подумай что будет для куба

подумаю (навскидку — то же самое, оверхед в районе 0.1%)

Я че то непойму, ты с ТС-ом что ли по упертости соревнуешься?

бугага!

совсем вкратце: мое поведение обоснованно

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

поэтому наличие инварианта в референсе — очень желательная вещь, даже несмотря на то, что инвариант может усложнить схему прохода по памяти (а он действительно может сильно усложнить, хотя и записан в 4 строки)

что же касается соревнования с ТС (слегка в другом аспекте — в вычислении экспоненты), то это традиция старого лор-а, и кроме того, ТС-у иначе хрен объяснишь что-то

добавлю, что твои отсылки к утверждениям типа «эти вопросы были исследованы 30-40 лет назад» стоят очень дешево — может быть ровно настолько дешево, сколько требуется для того, чтобы сразу же спросить «ну и какие же доводы за/против 30-40 лет назад были получены?»

понятно, что для занятия практической деятельностью заявления «так делают 30-40 лет» имеет определенный вес, но вовсе не для спора на лоре

так что не надейся на халяву — тут не начнут креститься на фразу «так делают 30-40 лет!!1111» как на икону

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

подумаю (навскидку — то же самое, оверхед в районе 0.1%)

По коду? Тогда подумай еще. Мемсп то тут нафига??? Тащем то там условие посложнее будет, надо выкидывать из суммы некоторые члены и менять соотв образом A. Ну или ставь периодические условия, но тогда в сумму надо другие члены на границах сувать.

твои отсылки к утверждениям типа «эти вопросы были исследованы 30-40 лет назад» стоят очень дешево

Я не википедия что бы объяснять (особенно существу типа ТС-а) какие то азбучные или не совсем азбучные истины. Я не учайствую в конкурсе «самый крутой спорщик ЛОР-а». Поэтому мне абсолютно пофигу, как мои отсылки выглядят. Хотите доказать что я не прав? Сделайте лучше, в чем проблема то;-)

Я интересующую меня постановку задачи озвучил, гран. условия в нее не входят. Именно потому, что при разумной организации по времени выполнения это доли процента, а сложность кода увеличивает кардинально. Т.е. ты можешь мне конечно не верить и кинуться пилить гран. условия - но это совсем-совсем другая задача;-)

наличие инварианта в референсе — очень желательная вещь

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

AIv ★★★★★
()
Ответ на: комментарий от AIv

Мемсп то тут нафига???

догадайся с 3 раз

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

если я конечно че-то не упустил, то у меня энергия сохраняется при условии бесконечно точного флоата (и да, я проверил это прогоном 1-ных значений в разных точках на границе)

посмотри внимательно

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

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от AIv

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

ну и как ты думаешь, у меня во всех тестовых прогонах были бы всегда нули на ребрах?

кроме того, даже на твоем решении видно, как чексумма немного падает при достаточно больших N

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от AIv

Я интересующую меня постановку задачи озвучил, гран. условия в нее не входят.

к.о. напоминает, что постановка задачи должна интересовать не только тебя — а иначе ее никто решать не будет

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

вот это примерно я и хочу от тебя услышать, но тем не менее я не убежден до сих пор

именно, действительно ли счет граничных условий будет занимать доли % при ЛЮБОМ РАЗУМНОМ обходе памяти для счета не-граничной части?

дело в том, что *отдельный* проход по границам это очень дорого — порядка 100 таков на каждый флоат

при кубической сетке 1К*1К*1К у нас будет границ 6М, т.е. 0.6% от внутренностей, и поэтому 100тактов*0.6%=0.6 такта оверхеда на каждый внутриграничный флоат; учитывая, что скорость прокачки памяти это ориентировочно 10 байтов на такт, т.е. 0.4 такта на флоат, мы имеем оверхед вовсе не в доли процента, а в 150% на весь бенчмарк (который, по-твоему, как раз прокачкой памяти и ограничен)

при квадратной сетке 32К*32К границ будет 128К, т.е. грубо говоря в 50 раз меньше, и оверхед будет порядка 150%/50=3%, что хотя и немного, но вовсе не доли процента

www_linux_org_ru ★★★★★
()
Последнее исправление: www_linux_org_ru (всего исправлений: 3)
Ответ на: комментарий от AIv

так вот, насчет сохранения тепла я до сих пор не уверен, как правильно, с ним или без него (а если ты *это* назовешь упертостью, то я порекомендую тебе сходить к доктору — проверить, не заболел ли ты сектанством от науки)

тут можно умыть руки и сделать 2 варианта на выбор того, кто будет проводить оптимизацию — вполне возможно, он выберет твой вариант, как более простой, да и я может быть тоже — но это не отменяет пользы разговора о границах :-)

да, еще надо сделать так, чтобы решение не было симметрично (иначе можно считать на 1/8 площади) например, разбросать по квадрату несколько источников

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

догадайся с 3 раз

Не асилю. -1 и N вообще невалидные значения индекса.

если я конечно че-то не упустил, то у меня энергия сохраняется при условии бесконечно точного флоата

Пппц.... коллеги, энергия сохраняется с машинной точностью ес-но. И, если мы фиксируем численную схему (а мы фиксируем схему) - то для данных н.у. и г.у. совпадают все знаки во всех точках при одном и том же моменте времени, вне зависимости от алгоритма (порядка обхода). Но! Хранить дампы для сравнения это бредовая идея (ИМНО) - они могут быть большие. Восстанавливать тем более. И главное, нафига этим заниматься если есть аналитическое решение то???

даже на твоем решении видно, как чексумма немного падает при достаточно больших N

На малых временах не должна. На больших временах - если все работает на малых, то на больших тоже работает;-)

к.о. напоминает, что постановка задачи должна интересовать не только тебя — а иначе ее никто решать не будет

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

дело в том, что *отдельный* проход по границам это очень дорого

Ес-но так не делают, г.у. обрабатываются в общем проходе.

AIv ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

это не отменяет пользы разговора о границах

Разговор о границах очень полезен. Но говорить о границах можно лишь после того как разберемся с центральной частью, потоку как границы это вообще то ппц как сложно (если их делать хорошо). В LRnLA (с конусами минковского) 99% работы именно с границами связано, и кодогенератор там именно из за границ припахан.

да, еще надо сделать так, чтобы решение не было симметрично

С т.з. физики - да, но с т.з. физики так решать эту задачу никакого смысла нету. С т.з. бенчмарка н.у. вообще пофигу, можно хоть нули гонять. Я одну единичку задал для приличия;-)

AIv ★★★★★
()
Ответ на: комментарий от AIv

Пппц.... коллеги, энергия сохраняется с машинной точностью ес-но.

возможно, я непонятно выразился, но смысл был в том, что аналитическая схема, если я где-то что-то не зевнул (как те 2 ребра), должна сохранять энергию; а на практическом прогоне естественно нет — энергия очень медленно шла наверх

Не асилю. -1 и N вообще невалидные значения индекса.

я же четко сказал, что массив N*(N+2), т.е. (очевидно) специально расширен под индексы -1 и N

могу вообще запостить полный код

но смысл в том, что добавляется 2 лишних ряда, температура которых каждую итерацию делается равной соседям как раз с помощью memcpy — в результате нет необходимости менять формулу расчета... если я опять че-нить не зевнул

www_linux_org_ru ★★★★★
()
Последнее исправление: www_linux_org_ru (всего исправлений: 1)
Ответ на: комментарий от AIv

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

мда... придется объяснять по аналогии

вот, например, люди бегают стометровку из спортивного интереса

а представь, что стометровку надо было бы бежать в несколько кругов диаметром 6 м — интерес бы явно поуменьшился

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

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

энергия очень медленно шла наверх

Если только ошибка округления?

я же четко сказал, что массив N*(N+2), т.е. (очевидно) специально расширен под индексы -1 и N

Тогда уже (N+2)*(N+2)?

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

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

ЗЫ понимаишь, вот мы новый код пишем - все обкатывается на очень простых, примитивных постановках. Пока все не вылизал - смылса че то боевое считать никакого, ХЗ откуда там кракозябры полезут - то ли это физика, то ли лирика, то ли ошибки в коде, то ли пятна на солнце...

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

AIv ★★★★★
()
Последнее исправление: AIv (всего исправлений: 1)
Ответ на: комментарий от www_linux_org_ru

на практическом прогоне естественно нет — энергия очень медленно шла наверх

тьфу на тя. Ты когда «энергию» бушь считать с такими г.у., края то не учитывай... и все будет стоять на месте.

AIv ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.