Re[12]: вопрос hi_octane про c#
От: vdimas Россия  
Дата: 06.09.20 01:20
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>А без неё сделать нельзя — expression trees не позволяют заводить временные переменные и делать присваивания. Это ограничение было бы дефектом, если бы оно не упрощало компилятор и не гарантировало отсутствие побочных эффектов, в отличие от настоящих присваиваний.


В линк-тайм кодогенерации компилятор сам разберется, где есть побочные эффекты, а где нет, даже если ты не собирался вникать и отделять вручную одни от других.
(и это говорилось более одного раза в те самые прошлые разы)
Re[12]: вопрос hi_octane про c#
От: vdimas Россия  
Дата: 06.09.20 01:25
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Вы устанете искать сценарий, в котором статическое порождение кода выиграет что-то заметное у динамики.


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


S>А вот сценариев проигрыша — масса.


Разве что для случая херак-херак и в продашен.
Re[11]: вопрос hi_octane про c#
От: Sinclair Россия https://github.com/evilguest/
Дата: 06.09.20 04:55
Оценка:
Здравствуйте, vdimas, Вы писали:

V>1. Я не вижу там поборотого выхода за границы для случаев, когда расстояние до соседа не есть некая константа.

А он есть. В "плохих" случаях просто просядет производительность — в коде останутся ветвления.
V>2. И это всё далеко не "базовая архитектура". За потраченную тобой трудоёмкость более-менее приемлемый велосипед можно и на плюсах навертеть.
Ждём с нетерпением.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[13]: вопрос hi_octane про c#
От: Sinclair Россия https://github.com/evilguest/
Дата: 06.09.20 04:58
Оценка:
Здравствуйте, vdimas, Вы писали:

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

Дело не в линк-тайм кодогенерации, а в сложности самописанного компилятора для Expressions.
Если мы разрешаем произвольный код, то банальный linq2db придётся раза в три раздуть в размерах. Потому что надо будет отслеживать множественные присваивания, т.е. переводить всё в SSA-форму, и далее со всеми остановками.
Практической полезности будет нуль, зато скорость компиляции даже простых случаев сильно просядет.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[13]: вопрос hi_octane про c#
От: Sinclair Россия https://github.com/evilguest/
Дата: 06.09.20 05:03
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, Sinclair, Вы писали:


S>>Вы устанете искать сценарий, в котором статическое порождение кода выиграет что-то заметное у динамики.


V>Это работает ровно до тех пор, пока работает аргумент "все-равно база тормозит".

Нет, почему. Вот, для того же linq2d — сравниваем динамику с кэшированием против статики (ручного выписывания аналогичного кода), выигрыша не видим. Никаких сотен миллисекунд — даже один процент наиграть не удаётся.
Автоматическая векторизация при этом позволяет отказаться от статического порождения кода под все варианты целевых платформ.
Ну и зачем было огород городить?
S>>А вот сценариев проигрыша — масса.
V>Разве что для случая херак-херак и в продашен.
Ну, так нам этот случай и интересен. Потому что время хочется тратить не на борьбу с ручным вылизыванием обхода массива, а на выбор алгоритмов.
Вон, как в Савола — на numpy предлагается реализация с двойным проходом для пре-аггрегирования.
Бенчмарк показывает, что эффективнее проходить один раз. Высокоуровневый код позволяет проверить эти гипотезы за минуты.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[12]: вопрос hi_octane про c#
От: vdimas Россия  
Дата: 06.09.20 10:39
Оценка:
Здравствуйте, Sinclair, Вы писали:

V>>1. Я не вижу там поборотого выхода за границы для случаев, когда расстояние до соседа не есть некая константа.

S>А он есть. В "плохих" случаях просто просядет производительность — в коде останутся ветвления.

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


V>>2. И это всё далеко не "базовая архитектура". За потраченную тобой трудоёмкость более-менее приемлемый велосипед можно и на плюсах навертеть.

S>Ждём с нетерпением.

Я тебе показывал в прошлом обсуждении велосипед даже на unsafe C#.
Re[13]: вопрос hi_octane про c#
От: Sinclair Россия https://github.com/evilguest/
Дата: 06.09.20 10:51
Оценка: +1 :)
Здравствуйте, vdimas, Вы писали:

V>Т.е., всё было насмарку, бо в плюсах константа может быть параметром кодогенерирующего шаблона, где ветвления уходят.

Если константа — то ветвления уходят. Даже если это рантайм константа. Как в примере с Sauvola, где константа — размер окна.
Плюсы отдыхают.

V>Я тебе показывал в прошлом обсуждении велосипед даже на unsafe C#.

Тот велосипед так и не поехал, а по производительности отстаёт от linq2d.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[14]: вопрос hi_octane про c#
От: vdimas Россия  
Дата: 06.09.20 10:55
Оценка: -1
Здравствуйте, Sinclair, Вы писали:

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

S>Дело не в линк-тайм кодогенерации, а в сложности самописанного компилятора для Expressions.

Выглядит так, что ты зациклился на C#. ))
Плевать с высокой колокольни на Expressions.
Твои потуги вокруг него любопытны, но малость непроизводительны, с т.з. затраченного на это времени.
А интерпретация полученных в прошлый раз результатов и вовсе была натуральной лысенковщиной, и это при твоей (на словах) приверженности "чистой науке" в других обсуждениях. ))

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

Догадался уже — почему?
В первый "раунд" мне стоило только вникнуть и я нашёл как поломать твоё решение (которое тогда уже было аж за версией 3).

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

В обоих случаях цена твоему "экспертному мнению" получилась примерно нулевая.


S>Если мы разрешаем произвольный код, то банальный linq2db придётся раза в три раздуть в размерах. Потому что надо будет отслеживать множественные присваивания, т.е. переводить всё в SSA-форму, и далее со всеми остановками.


Спор у вас там шёл не только о конкретно linq2db, а вообще о классах решаемых с помощью linq задач (с твоей подачи, кстате).
Это ведь именно твоя была странная позиция — позиционировать linq туда, куда его изначально никто не позиционировал.

Разве ты не обратил внимание, что никто из твоих собеседников не отрицал удобство этого инструмента, а глумились лишь над его эффективностью? ))


S>Практической полезности будет нуль, зато скорость компиляции даже простых случаев сильно просядет.


ХЗ, сейчас ничего сказать не могу, уже объяснил почему.

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

И так до тех пор, пока не научишься спорить корректно, ну хотя бы сугубо по предмету спора (фиг даже с твоей неспособностью удержаться от постоянных шпилек в адрес оппонента к месту и не к месту, их твои постоянные оппоненты уже научились более-менее фильтровать)
Отредактировано 06.09.2020 11:00 vdimas . Предыдущая версия .
Re[14]: вопрос hi_octane про c#
От: vdimas Россия  
Дата: 06.09.20 11:56
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>>>Вы устанете искать сценарий, в котором статическое порождение кода выиграет что-то заметное у динамики.

V>>Это работает ровно до тех пор, пока работает аргумент "все-равно база тормозит".
S>Нет, почему. Вот, для того же linq2d — сравниваем динамику с кэшированием против статики (ручного выписывания аналогичного кода), выигрыша не видим. Никаких сотен миллисекунд — даже один процент наиграть не удаётся.

Поиграй с распространением констант в С++.

Правда, есть та тонкость, что распространение констант хорошо работает с целочисленными вычислениями, а с плавающей точкой когда — в процессорах x86_x64 даже такой инструкции нет (умножить на произвольную константу) — всё-равно число подгружается из памяти по адресу. Именно поэтому векторные операции и заруливают обычную арифметику с плавающей точкой, что за один раз можно указать адреса нескольких операндов (вектора их), бгг...

Фишка в том, что и обычная и векторная арифметика используют одни и те же аппаратные блоки ядер, т.е. унутре проца всё происходит с одинаковой скоростью, т.е. выигрыш сугубо "архитектурный" получается, а не волшебный-аппаратный. Поэтому, если векторные регистры используются не для векторных операций (а там есть и не векторные, ими можно как обычным файлом регистров распоряжаться), то быстродействие получается такое же. А чуть лучше оно получается в не-векторных операциях от того, что векторные регистры рассматриваются как дополнительный файл регистров, т.е. трафик общения проца и кеша 0-го уровня может быть заметно ужат.

И да, что с чем ты собрался сравнивать?
Один запрос linq компиллируется от единиц до десятков ms.
Это не в синтетическом тесте, где один и тот же запрос компиллируется в цикле — а замеры на реальных приложениях.
Грубо, одну форму открыть — сотни ms только на компиляцию нескольких linq-запросов (обычно 3-5 на форму).
Приложение долго стартует (с заметной задержкой), долго открывает экраны (особенно, когда некий экран открывается в первый раз).

И твой кодогенератор, когда впервые отрабатывает — тоже сам по себе тормозит, на JIT и всё прочее.
т.е. еще до того, как начнёт работать.
И даже когда начнёт — первый раз сильно тормозит.

Для примера, замена просто кода, типа:
SomeScheme s1 = new ...;
s1.Add(a, b, "c");
s1.Add(e, f, "g");
...
s2.Add...

На вручную сериализованные данные ускорило старт приложения с ~800 ms до ~200 ms, т.е. 600 ms отъедалось лишь на инициализацию, т.е. первый (и последний) прогон некоего кода, примерно эквивалентного показанному.

Далее.
Всякие многократно упомянутые тобой "стратегии подстановки несуществующих точек" (жёстко задаваемые в коде, обычно) и прочее — ты, действительно, не в курсе, что на плюсах чуть ли не половина (если не большая часть) всего современного кода (сидящего поверх STL и Boost) — это стратегии стратегиями подгоняют?
"По глазам вижу" (С), что знал.
(помню прошлые обсуждения с тобой, кое-какое представление о плюсовых шаблонах ты имеешь)


S>Автоматическая векторизация при этом позволяет отказаться от статического порождения кода под все варианты целевых платформ.


Это если под x86.
Ты ведь курсе, например, что в природе нет активных поддерживаемых x86-х сборок Линукс?
Они все давно переползли на x86_x64, а там изкоробки 32 и 64-битные векторные операции, т.е. куча поколений, которые были для x86 — они пропущены для случая x86_x64.

Более поздние расширения могут пригодиться лишь в тех уникальных случаях, где надо оперировать векторами из памяти, длиной более 4-х (8 и 16), но это не твой случай, когда речь о представлении цвета.


S>>>А вот сценариев проигрыша — масса.

V>>Разве что для случая херак-херак и в продашен.
S>Ну, так нам этот случай и интересен.

Для заказухи если — может быть.
Ты попробуй коробочный подобный продукт продай — в том же магазине приложений смартфонов или "просто на рынке приложений". ))
Оглянись по сторонам, плиз, какого уровня идёт современное ПО.
Такое ощущение (из твоей подачи), что ты продолжаешь жить реалиями середины 2000-х.
За что тогда охотно платили бабки, сегодня это всё доступно абсолютно даром и даже в куче независимых реализаций.
В общем, ты попробуй заставь юзера выложить денюжку за "херак-херак".


S>Потому что время хочется тратить не на борьбу с ручным вылизыванием обхода массива, а на выбор алгоритмов.


Я тебе показывал хелперы даже для unsafe C#, просто чтобы показать идею.
На плюсах там в разы больше навертеть можно.

Если есть задача — под неё всё-равно хелперы писать надо.
Например, для оперирования цветами с альфа-каналами — свои хелперы.
Причём, от эффективности этих хелперов производительность зависит не меньше, чем от эффективности обхода массива.

И откуда вообще взялось предположение, что под некий класс задач (буде он возник), не пишут соответствующие хелперы?
А то ты там свои навороты натурально с чистым Си сравнивал, разве ж это спортивно? ))


S>Вон, как в Савола — на numpy предлагается реализация с двойным проходом для пре-аггрегирования.

S>Бенчмарк показывает, что эффективнее проходить один раз. Высокоуровневый код позволяет проверить эти гипотезы за минуты.

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

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

Любые эксперименты начинаются с воссоздания окружения "под задачу".
Вот даже ты этим занялся, хотя на C# это совсем не жёсткое правило, бо там многое есть изкаробки, но ты же занялся? ))
А по итогу сравниваешь некий фреймворк, отожравший дохрена времени, с голым Си...
Ну вот поэтому опять неинтересно.

И особенно неинтересна примерно такая наивность: "я тут потратил прилично времени я СДЕЛАЛ!!! а теперь сделайте ВЫ, или позорно убегайте!!!"
Честный исследователь бы сам (бо не маленький) исследовал бы основные мейнстримовые инструменты мейнстримовых платформ и выдал бы уже готовое честное сравнение.
(как это делаю я, когда что-то с чем-то сравниваю)

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

А, главное — зачем?
Найденные в твоём решении косяки не произведут на тебя впечатления, точно так же как проигрыш в производительности тоже не произведёт впечатления.

Это знаешь, как с Роем Джонсоном когда-то супертяжи отказывались драться: потому что проиграть поднявшемуся на 3 весовые категории средневесу стыдно.
А выигрывать тоже нифига не почётно.
Вот примерно так и у тебя — косяки будут объяснены "кругом решаемых задач" или даже "постановкой задачи", а проигрыш в производительности (в зависимости от его размера) может быть мгновенно перевёрнут в "победу", через рассуждения примерно такого плана: "вот видите, мы практически достигли производительности нейтива, хотя продолжаем оставаться в рамках высокоуровневого инструмента" и далее миллион вот этих бесконечнейших спекуляций на тему, "почему высокоуровневое лучше". Осталось выяснить, почему высокоуровневым может быть решение только на C#, а другим низзя? ))
Отредактировано 06.09.2020 12:26 vdimas . Предыдущая версия . Еще …
Отредактировано 06.09.2020 12:26 vdimas . Предыдущая версия .
Отредактировано 06.09.2020 12:21 vdimas . Предыдущая версия .
Отредактировано 06.09.2020 12:16 vdimas . Предыдущая версия .
Re[14]: вопрос hi_octane про c#
От: vdimas Россия  
Дата: 06.09.20 12:02
Оценка: -2
Здравствуйте, Sinclair, Вы писали:

V>>Т.е., всё было насмарку, бо в плюсах константа может быть параметром кодогенерирующего шаблона, где ветвления уходят.

S>Если константа — то ветвления уходят. Даже если это рантайм константа. Как в примере с Sauvola, где константа — размер окна.
S>Плюсы отдыхают.

Где отдыхают?
Ты ведь опять самонадеянно разбрасываешься словами, cнижая их цену до 0-ля.


V>>Я тебе показывал в прошлом обсуждении велосипед даже на unsafe C#.

S>Тот велосипед так и не поехал

Еще и врёшь.
Велосипед прекрасно поехал.

Да, я помню, что ты мне пенял на то, что я реализовал в первой версии не тот алгоритм.
Мне плевать было, потому что плевать велосипеду — он одинаковый для любых алгоритмов.
Я переделывал алгоритм на верный — мало что изменилось, т.е. пятиминутное потраченное время не уступило твоему решению в эффективности.
Натурально пятиминутное.


S>а по производительности отстаёт от linq2d.


Врешь.
От прошлого твоего варианта не отставал.

А в нынешнем ты замахнулся на нейтив, дык, с ним и надо сравнивать.
Только не с Си-подобной версией, ес-но.

Перепиши так сравниваемый код, чтобы у компилятора были хоть как-то развязаны руки.
Re[15]: вопрос hi_octane про c#
От: Sinclair Россия https://github.com/evilguest/
Дата: 06.09.20 17:38
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Где отдыхают?

V>Ты ведь опять самонадеянно разбрасываешься словами, cнижая их цену до 0-ля.
Там и отдыхают. Давайте попробуем передать константу в рантайме, и посмотрим, удастся ли что-то там сэкономить на плюсах.
А вы, коллега, беспардонно передёргиваете:

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

И тут же:

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

Так константа или не константа?

V>Еще и врёшь.

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

V>От прошлого твоего варианта не отставал.

От нового отстанет.
V>А в нынешнем ты замахнулся на нейтив, дык, с ним и надо сравнивать.
V>Только не с Си-подобной версией, ес-но.
А с какой?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[15]: вопрос hi_octane про c#
От: Sinclair Россия https://github.com/evilguest/
Дата: 06.09.20 17:46
Оценка:
Здравствуйте, vdimas, Вы писали:
V>Поиграй с распространением констант в С++.
Это вообще о чём?
Давайте пример кода, а то за вашим полётом мысли я не успеваю.

V>И да, что с чем ты собрался сравнивать?

V>Один запрос linq компиллируется от единиц до десятков ms.
V>Это не в синтетическом тесте, где один и тот же запрос компиллируется в цикле — а замеры на реальных приложениях.
V>Грубо, одну форму открыть — сотни ms только на компиляцию нескольких linq-запросов (обычно 3-5 на форму).
V>Приложение долго стартует (с заметной задержкой), долго открывает экраны (особенно, когда некий экран открывается в первый раз).
Хм. Надо профилировать.
V>И твой кодогенератор, когда впервые отрабатывает — тоже сам по себе тормозит, на JIT и всё прочее.Х
Это да — надо прогревать заранее. Там, где есть потенциальная возможность статической оптимизации, она есть — можно использовать то самое кэширование на старте.
Ну, а если стартап тоже важен, то включаем галочку "сохранять сборку", и код можно породить на стороне разработчика, а потом включить готовую сборку в поставку приложения.

V>Для примера, замена просто кода, типа:

V>
V>SomeScheme s1 = new ...;
V>s1.Add(a, b, "c");
V>s1.Add(e, f, "g");
V>...
V>s2.Add...
V>

V>На вручную сериализованные данные ускорило старт приложения с ~800 ms до ~200 ms, т.е. 600 ms отъедалось лишь на инициализацию, т.е. первый (и последний) прогон некоего кода, примерно эквивалентного показанному.
Я не знаю, что это за код, и почему он требует 600ms на исполнение.
V>(помню прошлые обсуждения с тобой, кое-какое представление о плюсовых шаблонах ты имеешь)
Ну и что?
V>Это если под x86.
И под ARM тоже.
V>Ты ведь курсе, например, что в природе нет активных поддерживаемых x86-х сборок Линукс?
V>Они все давно переползли на x86_x64, а там изкоробки 32 и 64-битные векторные операции, т.е. куча поколений, которые были для x86 — они пропущены для случая x86_x64.
А что насчёт 128 и 256? С 512 пока засада — нет поддержки в CLR.
V>Более поздние расширения могут пригодиться лишь в тех уникальных случаях, где надо оперировать векторами из памяти, длиной более 4-х (8 и 16), но это не твой случай, когда речь о представлении цвета.
С чего бы это вдруг? С цветами всё заработает прекрасно в AVX2.

V>Я тебе показывал хелперы даже для unsafe C#, просто чтобы показать идею.

V>На плюсах там в разы больше навертеть можно.
Угу, угу.
V>Если есть задача — под неё всё-равно хелперы писать надо.
V>Например, для оперирования цветами с альфа-каналами — свои хелперы.
Конечно.
V>Причём, от эффективности этих хелперов производительность зависит не меньше, чем от эффективности обхода массива.
И их можно сочетать с linq2d.
V>И откуда вообще взялось предположение, что под некий класс задач (буде он возник), не пишут соответствующие хелперы?
V>А то ты там свои навороты натурально с чистым Си сравнивал, разве ж это спортивно? ))
Давайте пример в студию — это будет конструктивно.

V>Тебе показывали реализацию на Питоне, которая не сложнее твоей на linq2d, зачем ты продолжаешь использовать тот аргумент, который уже бит?

Она медленнее

V>(как это делаю я, когда что-то с чем-то сравниваю)

Не вижу.

V>примерно такого плана: "вот видите, мы практически достигли производительности нейтива, хотя продолжаем оставаться в рамках высокоуровневого инструмента" и далее миллион вот этих бесконечнейших спекуляций на тему, "почему высокоуровневое лучше". Осталось выяснить, почему высокоуровневым может быть решение только на C#, а другим низзя? ))

Вы сначала покажите второе решение
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[16]: вопрос hi_octane про c#
От: alex_public  
Дата: 06.09.20 18:41
Оценка: -2
Здравствуйте, Sinclair, Вы писали:

_>>Ну приведи конкретный пример невозможного. А то уже много лет как есть вполне себе работающая именно по такому принципу библиотека...

S>
S>public IQueryable<OrderLine> GetOrderLines(DataConnection conn, int productID, DateTime? orderDateMin)
S>{
S>  var q = from line in conn.GetTable<OrderLine> where line.ProductID == productID select line;
S>  if(orderDateMin.HasValue)
S>    q = from line in q where line.Order.OrderDate>=orderDateMin.Value select line;
S>}
S>



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

_>>Насколько я помню в реальности там были накладные расходы в доли миллисекунды (а не микро!)/

S>Всё верно. Доли миллисекунды.

Для link2db. Для EF будут уже не доли. И это всё для простых запросов.

Да, и главное то не абсолютные цифры, а относительные. В том тесте это было соответственно +60 и +500 процентов.

_>>О, а вот подобное является следствием ещё одного недостатка linq: что он на самом деле не равносилен sql. Преобразования там достаточно не тривиальное, причём даже для человека. Помнится тут кидали примеры каких-то запросов и я не всегда сразу видел сколько же там внутри на самом деле join'ов и каких.

S>Это не недостаток. Писать на SQL я могу и без помощи "библиотек". Linq даёт выразительность настоящего языка программирования — в том числе и по декомпозиции запросов на более простые части.
S>Мы не любим SQL как раз за то, что у него всё очень плохо с повторным использованием.

Подожди, тут же не о том речь. Я сам не в восторге от sql по целому ряду причин. Но при этом если уж у нас выбран такой способ диалога с СУБД, то надо именно его придерживаться. Всё равно же в итоге генерируется sql и лучше если программист будет понимать какой.

_>>А вот если у нас dsl полностью равносильный нормальному sql, то никаких подобных проблем возникнуть просто не может.

S>
_>>Конечно. Но кто тут говорил про оптимизацию? Нормальная оптимизация возможна внутри СУБД (т.к. там у нас доступна вся статистика) и в голове программиста (т.к. он может использовать знания о модели данных в СУБД). А оптимизация запросов на стадии передачи их в СУБД — это какая-то ерунда, которая способна только на какие-то совершенно тривиальные действия.
S>Нет конечно. Семантическая оптимизация — устранение, к примеру, left outer join, или inner join по верифицированному foreign key, если в результате не используются поля присоединяемой таблицы. Такие штуки делают далеко не все СУБД, несмотря на то, что для них не нужна статистика. Большинство движков СУБД рассчитывают на то, что автор запроса не пишет фигни; они лучше всего работают тогда, когда им даётся предварительно урезанный до минимума запрос — тогда у оптимизатора хватает сил и времени на выбор оптимальной стратегии исполнения.

И что это за не все СУБД?

_>>А, ну т.е. использование в роли кэша глобальной переменной. Это возможно имеет какой-то смысл для твоей библиотечки, однако совсем не коррелирует с озвученными требованиями на динамические запросы (если говорить о link2databse).

S>В linq2db другая ситуация по соотношению времён компиляции и исполнения запросов. Там можно делать кэш по ExpressionTree — это упражнение выполнено в классической серии статей Matt Warren "Building an IQueryable provider".

И что у нас там является ключом кэша? )

_>>Компиляция то будет быстрее, а вот работать код будет намного медленнее. )))

S>Пруф можно?

Пруф на то, что C++ код будет быстрее C# кода?

_>>А так я в целом конечно же не против самой идее. Надо только чтобы реализация была адекватной. Вот например у WebAssembly практически всё адекватно в реализации (ну когда эта https://v8.dev/features/simd фича зарелизится во всех браузерах).

S>Ну, и слава байту.

Кстати, эта платформа рассчитана уже не только на браузеры. И заявлено уже много других разных применений. Так что не удивлюсь, если скоро и системные языки (C++, Rust и т.п.) будут активно использовать байт-код. Только в его адекватной версии, а не как в clr/jvm.
Re[15]: вопрос hi_octane про c#
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 06.09.20 20:20
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Поиграй с распространением констант в С++.

V>Правда, есть та тонкость, что распространение констант хорошо работает с целочисленными вычислениями, а с плавающей точкой когда — в процессорах x86_x64 даже такой инструкции нет (умножить на произвольную константу) — всё-равно число подгружается из памяти по адресу.

Мне вот стало тут интересно
1) Какая принципиальная разница между загрузкой константы из литерала команды и из сегмента данных, кроме лишнего косвенного доступа по регистру и возможной задержки на чтении памяти?
Или тебе они настолько принципиальны?

2) Чем тебе следующий подход непригоден?
0000000000000000 <foo>:
   0:   49 b8 88 77 66 55 44    movabs $0x1122334455667788,%r8
   7:   33 22 11 
   a:   66 49 0f 6e c0          movq   %r8,%xmm0


V> Именно поэтому векторные операции и заруливают обычную арифметику с плавающей точкой, что за один раз можно указать адреса нескольких операндов (вектора их), бгг...


Это действительно основная причина? )

V>Фишка в том, что и обычная и векторная арифметика используют одни и те же аппаратные блоки ядер, т.е. унутре проца всё происходит с одинаковой скоростью, т.е. выигрыш сугубо "архитектурный" получается, а не волшебный-аппаратный. Поэтому, если векторные регистры используются не для векторных операций (а там есть и не векторные, ими можно как обычным файлом регистров распоряжаться), то быстродействие получается такое же. А чуть лучше оно получается в не-векторных операциях от того, что векторные регистры рассматриваются как дополнительный файл регистров, т.е. трафик общения проца и кеша 0-го уровня может быть заметно ужат.


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

S>>Автоматическая векторизация при этом позволяет отказаться от статического порождения кода под все варианты целевых платформ.


V>Это если под x86.

V>Ты ведь курсе, например, что в природе нет активных поддерживаемых x86-х сборок Линукс?
V>Они все давно переползли на x86_x64,

У тебя какая-то инопланетная природа.
Debian, например, продолжает вести 32-битные образы.
Если постараться, ещё десяток можно поискать.

V> а там изкоробки 32 и 64-битные векторные операции, т.е. куча поколений, которые были для x86 — они пропущены для случая x86_x64.


Хотя что они хотят от процессора — слегка лень смотреть.

[skip остальное, тут надо плотно сесть на вашу траву, чтобы понять смысл дискуссии]
The God is real, unless declared integer.
Re[17]: вопрос hi_octane про c#
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 06.09.20 20:41
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Здравствуйте, Sinclair, Вы писали:


_>>>Ну приведи конкретный пример невозможного. А то уже много лет как есть вполне себе работающая именно по такому принципу библиотека...

S>>
S>>public IQueryable<OrderLine> GetOrderLines(DataConnection conn, int productID, DateTime? orderDateMin)
S>>{
S>>  var q = from line in conn.GetTable<OrderLine> where line.ProductID == productID select line;
S>>  if(orderDateMin.HasValue)
S>>    q = from line in q where line.Order.OrderDate>=orderDateMin.Value select line;
S>>}
S>>



_>Так это же вроде прямо в точности тот базовый пример, который показывал я в предыдущих сообщениях. Или я что-то не вижу в этом коде? Какой sql должен сгенерироваться?

Join для line.Order и
where line.ProductID = productID And line.Order.OrderDate>=orderDateMin.Value


_>Пруф на то, что C++ код будет быстрее C# кода?

_>>Компиляция то будет быстрее, а вот работать код будет намного медленнее. )))

Пруф на то, что работать код будет намного медленнее.
Можно взять примеры
https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-5/

Думал, что 3.1 это потолок, но и в .Net 5 нехило докрутили

Ну и для ARM64
https://devblogs.microsoft.com/dotnet/arm64-performance-in-net-5/

И показать во сколько раз нетовский код медленнее.
Студию можно взять отсюда
https://devblogs.microsoft.com/dotnet/arm64-performance-in-net-5/
и солнце б утром не вставало, когда бы не было меня
Отредактировано 06.09.2020 20:44 Serginio1 . Предыдущая версия .
Re[18]: вопрос hi_octane про c#
От: alex_public  
Дата: 06.09.20 22:09
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>>>Очень может быть. С нетерпением ждём примера С4 с nearest neighbour на языке с перегрузкой операторов.

_>>Так зачем мелочиться, вот https://github.com/manuelaguadomtz/pythreshold/blob/master/pythreshold/local_th/sauvola.py тебе пример целиком sauvola, причём для произвольного размера окна.
S>Да, почти так же просто, как в linq2d.

Не, любые математические выражения записываются намного проще. В первую очередь потому, что сама математика шла именно по такому пути, задолго до всяких компьютеров. Т.е. мы пишем условно a*b и это имеет очень разный смысл в зависимости от того, кто такой а (например константа, функция, оператор) и кто такой b (например скаляр, вектор, тензор). Однако математикам это удобно и привычно. И весь наш мат. аппарат разработан в расчёте именно на такой подход. Так что любой язык без возможности переопределения операторов (в зависимости от типа) — это дикое неудобство для записи математики.

_>>Если же усреднять только по соседям, то код ещё упростится.

S>Возможно, но не факт.

Для случая окна размером 3 пикселя (как раз твой код), собственно свёртку на numpy вообще по другому проще (и эффективнее) будет записать. А именно, сделать 4 сдвига нашей матрицы (причём можно без выделения памяти, как срез) и потом их просто сложить.

А вот основное выражение пороговой функции вообще никак не будет меняться и выглядит в точности как математическая формула в статье.

_>>Нет, это ты всё как раз обсуждаешь только вариант с недоверием и плохой производительностью. А для нормальной производительности у тебя должен быть стандартный способ получить sortedArray из array без сортировки. Да, это возможно будет такая "unsafe" операция, но она необходима для возможности написания производительного ПО.

S>Ну, если удастся доказать, что именно в этом проблема производительности, то можно реализовать и unsafe-конструктор sortedArray из array.

И в языке ориентированном на эффективность такие штуки обязательно будут от рождения.

_>>Таких библиотек полно и без linq и в более удобном формате. Но они работают только "со своим типом данных". Здесь же речь шла именно о стандартной работе с коллекциями.

S>Нет такого понятия, как "стандартная работа с коллекциями". Стандартом для linq к базам данных является EF. Это не мешает ему быть унылым говном, а нестандартный linq2db — прекрасная реализация.
S>Linq — это, по большому счёту, две фичи:
S>1. Поддержка Expression в языке
S>2. Поддержка query syntax.
S>Первое — принципиально, второе — приятная вишенка на торте.
S>Всё остальное напилено поверх языка, в меру умений программистов и испорченности архитекторов каждой реализации.

Правильно ли я понимаю, что с твоей точки зрения IEnumerable и IQueryable — это не часть Linq, а всего лишь какие-то там интерфейсы из неких прикладных библиотек?
Re[14]: вопрос hi_octane про c#
От: alex_public  
Дата: 06.09.20 22:20
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Вон, как в Савола — на numpy предлагается реализация с двойным проходом для пре-аггрегирования.

S>Бенчмарк показывает, что эффективнее проходить один раз. Высокоуровневый код позволяет проверить эти гипотезы за минуты.

Хы, ты похоже совсем не разобрался с этими алгоритмами.

Твой код работает как O(n^2), где n — это размер окна. А пример на numpy работает в этом смысле как O(1). Но при этом для n=3 (собственно минимальный размер окна и как раз тот случай, что ты рассматривается в твоём коде) это O(1) где-то раза в 3-4 (это я не измерял, а так, прикинул на глаз, смотря на код) медленнее твоего O(n^2). Однако уже при n=15 (кстати значения по умолчанию для размера окна твой функции на numpy) их код должен быть раз 5-10 быстрее твоего варианта с честным вычислением ядра каждый раз.
Re[17]: вопрос hi_octane про c#
От: Sinclair Россия https://github.com/evilguest/
Дата: 07.09.20 03:49
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Здравствуйте, Sinclair, Вы писали:


_>>>Ну приведи конкретный пример невозможного. А то уже много лет как есть вполне себе работающая именно по такому принципу библиотека...

S>>
S>>public IQueryable<OrderLine> GetOrderLines(DataConnection conn, int productID, DateTime? orderDateMin)
S>>{
S>>  var q = from line in conn.GetTable<OrderLine> where line.ProductID == productID select line;
S>>  if(orderDateMin.HasValue)
S>>    q = from line in q where line.Order.OrderDate>=orderDateMin.Value select line;
S>>}
S>>



_>Так это же вроде прямо в точности тот базовый пример, который показывал я в предыдущих сообщениях. Или я что-то не вижу в этом коде? Какой sql должен сгенерироваться?

Примерно такой:
select line.* from orderLines line 
  where line.productID = @productID

Или такой:
select line.* from orderLines line 
  inner join orders o on line.orderId = o.id
  where line.productID = @productID and o.orderDate >= @orderDateMin 

— в зависимости от того, что передано в качестве orderDateMin.

S>>Всё верно. Доли миллисекунды.

_>Для link2db. Для EF будут уже не доли. И это всё для простых запросов.
Ага, я вижу пробуждение понимания того, что затраты зависят не от технологии, а от конкретной реализации. Так-то я могу и на C++ наколбасить код, который будет тратить сотни миллисекунд на подготовку SQL.
_>Да, и главное то не абсолютные цифры, а относительные. В том тесте это было соответственно +60 и +500 процентов.
Совершенно верно
Но такие тесты опасно проводить в вакууме — можно сделать совершенно неверные выводы. К примеру, можно запустить такой запрос на пустой базе, и вернуть 0 записей за +60% от чистого SQL.
А можно запустить "лобовой" вариант запроса на продакшн-базе, и получить на "чистом" SQL +500% к времени исполнения по сравнению с "медленным" linq:
select line.* from orderLines line 
  inner join orders o on line.orderId = o.id
  where line.productID = @productID and (o.orderDate >= @orderDateMin or  @orderDateMin is null)  


_>Подожди, тут же не о том речь. Я сам не в восторге от sql по целому ряду причин. Но при этом если уж у нас выбран такой способ диалога с СУБД, то надо именно его придерживаться. Всё равно же в итоге генерируется sql и лучше если программист будет понимать какой.

Это какое-то странное рассуждение. Да, лучше, если программист будет понимать, какой код будет генерироваться. Но это совершенно не означает, что он обязан весь его выписывать руками.
Если мы отвлечёмся от SQL, то "способом диалога" с процессором у нас является бинарный код. Конечно же, будет лучше, если программист понимает, какой именно код там генерируется. Но надо ли придерживаться именно такого "способа диалога" при написании прикладных программ? Или можно всё же пользоваться языком высокого уровня, а раскладку данных по регистрам и выбор конкретных команд доверять компилятору?

S>>Нет конечно. Семантическая оптимизация — устранение, к примеру, left outer join, или inner join по верифицированному foreign key, если в результате не используются поля присоединяемой таблицы. Такие штуки делают далеко не все СУБД, несмотря на то, что для них не нужна статистика. Большинство движков СУБД рассчитывают на то, что автор запроса не пишет фигни; они лучше всего работают тогда, когда им даётся предварительно урезанный до минимума запрос — тогда у оптимизатора хватает сил и времени на выбор оптимальной стратегии исполнения.

_>И что это за не все СУБД?
Да практически в любую ткни. Приведённый пример прикрутили в MS SQL Server, емнип, году в 2012, если не позже. MySQL этого делать даже не пытается, насчёт Оракла и Постгре я сомневаюсь.

_>Пруф на то, что C++ код будет быстрее C# кода?

Да, конечно.

_>Кстати, эта платформа рассчитана уже не только на браузеры. И заявлено уже много других разных применений. Так что не удивлюсь, если скоро и системные языки (C++, Rust и т.п.) будут активно использовать байт-код. Только в его адекватной версии, а не как в clr/jvm.

Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[19]: вопрос hi_octane про c#
От: Sinclair Россия https://github.com/evilguest/
Дата: 07.09.20 03:57
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Не, любые математические выражения записываются намного проще.

Конкретный пример лично для меня проще не выглядит. И он, кстати, на первый взгляд медленнее linq2d реализации — потому что использует больше операций и промежуточных массивов, а это не может быть бесплатным.
Я не очень хорошо знаком с numpy, но либо они используют порождение кода на лету (т.е. аналог linq), либо получают существенное замедление.
Можете напилить бенчмарк с предложенной вами реализацией?

_>В первую очередь потому, что сама математика шла именно по такому пути, задолго до всяких компьютеров. Т.е. мы пишем условно a*b и это имеет очень разный смысл в зависимости от того, кто такой а (например константа, функция, оператор) и кто такой b (например скаляр, вектор, тензор). Однако математикам это удобно и привычно. И весь наш мат. аппарат разработан в расчёте именно на такой подход. Так что любой язык без возможности переопределения операторов (в зависимости от типа) — это дикое неудобство для записи математики.

Как хорошо, что таких языков практически не осталось.

_>Для случая окна размером 3 пикселя (как раз твой код), собственно свёртку на numpy вообще по другому проще (и эффективнее) будет записать. А именно, сделать 4 сдвига нашей матрицы (причём можно без выделения памяти, как срез) и потом их просто сложить.

Давайте от абстрактных рассуждений перейдём к коду. Как будет выглядеть сложение этих сдвигов?

_>Правильно ли я понимаю, что с твоей точки зрения IEnumerable и IQueryable — это не часть Linq, а всего лишь какие-то там интерфейсы из неких прикладных библиотек?

Конечно. Их можно убрать, и в языке ничего не изменится.
Также, как numpy не является частью языка Python.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[15]: вопрос hi_octane про c#
От: Sinclair Россия https://github.com/evilguest/
Дата: 07.09.20 04:09
Оценка:
Здравствуйте, alex_public, Вы писали:
_>Твой код работает как O(n^2), где n — это размер окна.
Нет конечно. Он точно так же вычисляет сумму и сумму квадратов через предварительно рассчитанные интегралы.
Только питоновский вариант вычисляет интегралы за четыре прохода по исходному массиву, а C#-ный — за 1.
Ну, и окончательный расчёт порога там делается без ветвлений в коде цикла и с использованием SIMD.
А на питоне я пока не могу понять, материализуются ли массивы x1/y1 и x2/y2 перед исполнением, или же значения "элементов" динамически вычисляются уже в процессе расчёта каждого значения выходного массива.

_> А пример на numpy работает в этом смысле как O(1). Но при этом для n=3 (собственно минимальный размер окна и как раз тот случай, что ты рассматривается в твоём коде) это O(1) где-то раза в 3-4 (это я не измерял, а так, прикинул на глаз, смотря на код) медленнее твоего O(n^2). Однако уже при n=15 (кстати значения по умолчанию для размера окна твой функции на numpy) их код должен быть раз 5-10 быстрее твоего варианта с честным вычислением ядра каждый раз.

В бенчмарке, который опубликован в гитхабе, размер окна равен 11.
Давайте замерим, насколько быстрее будет питоновский код.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.