Re[15]: Бинарная склейка
От: vdimas Россия  
Дата: 24.01.17 14:33
Оценка:
Здравствуйте, Qbit86, Вы писали:

V>>Именно это позволяет бороться с распуханием кода после применения шаблонов.

Q>И насколько успешно позволяет?

Ну, в несколько раз конечный образ обычно уменьшается.

Например, если скомпиллять с агрессивной релизной оптимизацией и порождением PDB, а потом походить по исходнику в отладчике пошагово, то я ловил такие фокусы, что обрабатываются, скажем, поля с типами int32, а вызываются ф-ии (по исходнику) для совсем других полей с другим типом — float32.

Когда-то лет 18 назад я впервые такое обнаружил в MS VC 6.0 и мне показалось, что отладчик глючит, сцуко. Переключил в ассемблерный вид — ан нет, всё верно.
Re[16]: Бинарная склейка
От: Qbit86 Кипр
Дата: 24.01.17 14:46
Оценка:
Здравствуйте, vdimas, Вы писали:

V>>>Именно это позволяет бороться с распуханием кода после применения шаблонов.

Q>>И насколько успешно позволяет?
V>Ну, в несколько раз конечный образ обычно уменьшается.

Ну смотри. Я компилировал указанные выше четыре исходника в MSVS 2015 в статическую библиотеку. В вариантах оптимизации «Minimize Size (/O1)» и «Full Optimization (/Ox)», в Release. Runtime Library: «Multi-threaded DLL (/MD)». Получил последовательно бинарники: 810 KB, +22 KB, +21 KB, +26 KB. Выглядит так, будто каждый последующий explicit instance просто раздувает на пару десятков килобайт, не разделяя кода. Что упущено; из-за чего эффект от оптимизации распухания кода незаметен?
Глаза у меня добрые, но рубашка — смирительная!
Re[15]: «Собаку съел»
От: alex_public  
Дата: 24.01.17 16:19
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Бинго! На этом посте имхо и стоит закрыть эту тему. Потому что вы 777 778 постов пережёвываете две мысли:

S>"с соблюдением _всех_ контрактов современного фреймворка часть оптимизаций практически невозможна"

Верно. Тут не раз отмечалось, что основные проблемы сосредоточены в самом .net, а не в языках.

S>и

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

  Оффтопик
Лучше говорить о сравнение с C/C++ (как лидера по быстродействию в данное время), а не просто о нативном коде. А то там кроме C/C++ могут встречаться и Objective-C с Delphi и OCaml с Haskell и D с Rust. И у всех них очень разные ситуации с быстродействием. )))

Тоже верно, но с одной существенной натяжкой. Для получения быстродействия, сравнимого с C/C++, программисту обязательно придётся активно использовать unsafe код, непосредственную работу с памятью и стеком, хорошо знать тонкости работы процессора и т.п. Т.е. не получится фокуса, что мы просто перекомпилируем стандартный код на C# под .net native и если он заведётся (не использует всякие нехорошие рефлексии и т.п.), то автоматически получим быстродействие C/C++. Нет, подобный код придётся писать целенаправленно и при этом программист будет обязан иметь высокую квалификацию. А это уже убивает одно из главных преимуществ C# над C++.

Кстати, я тут в соседней темке уже давал эти ссылки по другому вопросу, но в контексте этой нашей дискуссии они тоже могут быть очень любопытны. Вот https://databricks.com/blog/2015/04/28/project-tungsten-bringing-spark-closer-to-bare-metal.html и вот https://databricks.com/blog/2016/05/23/apache-spark-as-a-compiler-joining-a-billion-rows-per-second-on-a-laptop.html — посмотри как в мире Java борются со многими проблемами, происходящими из самой платформы. Подозреваю, что для очень многих рядовых программистов на Java подобные вопросы относятся к чему-то типа чёрной магии. ))) Хотя это всего лишь самые базовые понятия для любого нормального C/C++ программиста.

Да, и кстати большинство этих их рассуждение опирается на неплохой по оптимизации (во всяком случае для JIT) компилятор из J9 от IBM. Раньше он входил только в их сомнительные продукты, но недавно они выложили все ключевые компоненты в Eclipse OMR и оно активно пошло в массы. Так что с этой стороны тоже идут активные инициативы в сторону быстродействия. Но опять же до мира C/C++ и им тоже очень далеко.

S>Особый юмор ситуации в том, что вторая мысль проверена практикой уже несколько лет как. Приложения под WP 8 — managed с прекомпиляцией. Почти все встроенные метро-приложения Win 10 — шарп + .net native. нетормозят™.


Очень сомнительный аргумент. У меня вот есть несколько приложений на Питоне, которые тоже абсолютно не тормозят. Но при этом я не делаю из этого выводов, что Питон способен сравниваться с нативным кодом по быстродействию.

S>Вопрос по сути в следующем:

S>* когда аналог .native будет доступен для прочих форков дотнета (ориентировочно — через релиз).

А разве где-то вообще заявлялось, что будет движение в этом направление? )

S>* когда по качеству оптимизации транслированный код будет выигрывать у выхлопа JIT-а (ещё позднее).


А разве там ещё не прикрутили бэкенд от их компилятора для C++? Тут Serginio1 уже всё заспамил ссылками на эту тему. )))
Re[16]: «Собаку съел»
От: Sinix  
Дата: 24.01.17 16:23
Оценка:
Здравствуйте, vdimas, Вы писали:

В основном согласен, мелкие поправки

S>>"с отказом от части контрактов в плане оптимизаций дотнет принципиально ничем не отличается от нативного кода".

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

Текущая политика — верификация при трансляции в натив. Она позволяет ещё больше вольностей в обращении с кодом. Для UWP трансляция происходит в облаке, для остального возможно распространение уже готовых бинарников под каждую платформу, возможно, будет вариант с распространением по аналогии с ngen, аля вот так:

The .appxupload contains the MSIL binaries as well as an explicit reference to the version of the .NET Native toolchain your app consumes (referenced in the AppxManifest.xml).

(с).

Чисто технических препятствий для локальной верификации для десктопов и серверов нет, главный бонус от "компилятора в облаке" — экономия батарейки и ускорение установки на мобильных устройствах. Ну, т.е. прекомпиляция потому что маркет, а не наоборот


V>Проблема исключительно и только в рефлексии всего и вся.

Ну... не совсем так. Главный затык _сейчас_ — инлайнинг делегатов / интерфейсов (хотя бы итераторов для начала) и stackallock объектов (не факт, что он появится в .native раньше, чем в .net core). "Сейчас" — это с хайпом на облака акторов и на соревновалки в 1M rps. А вот когда (и если) дело пойдёт в сторону числодробилок, тогда — да, cross-assembly optimizations в полный рост.


S>>* когда по качеству оптимизации транслированный код будет выигрывать у выхлопа JIT-а (ещё позднее).

V>А вот это тогда, когда перейдут на принципиально другую VM. Собсно, унутре майкрософтных оптимизирующих продуктов есть промежуточное представление навроде LLVM.
В смысле перейдут? у .net native свой runtime прямо сейчас. Ну и кроме .net native есть ещё пара запасных pipelines, как ты и писал.

V>Более того, с выпуском VS 15 они теперь могут поддерживать оптимизацию байт-кода LLVM.

llilc даже до беты не дошёл ещё. Кто его там в релиз собирался впихивать??? Или речь про IL2CPP от unity?


Остальное поскипал, т.к. спор и без меня не заглохнет
Re[17]: Бинарная склейка
От: vdimas Россия  
Дата: 24.01.17 16:29
Оценка:
Здравствуйте, Qbit86, Вы писали:

V>>Ну, в несколько раз конечный образ обычно уменьшается.

Q>Ну смотри. Я компилировал указанные выше четыре исходника в MSVS 2015 в статическую библиотеку.

Считай, что статическая библиотека при включенной опции "link time code generation" — это просто некий байт-код. ))


Q>Что упущено; из-за чего эффект от оптимизации распухания кода незаметен?


Упущена стадия релизной кодогенерации конечного бинарного образа.

Вот простой пример:
#include <vector>

int main()
{
    std::vector<int> ints;
    std::vector<float> floats;

    ints.push_back(1);
    floats.push_back(1);

    return 0;
}


Вот его дисассемблинг в отладчике в релизе:
    ints.push_back(1);
0014104D  lea         ecx,[ints]  
00141050  mov         byte ptr [ebp-4],1  
00141054  call        std::vector<float,std::allocator<float> >::_Reserve (0141140h)  
...

    floats.push_back(1);
014106A  lea         ecx,[floats]  
0014106D  mov         dword ptr [ebp-20h],eax  
00141070  call        std::vector<float,std::allocator<float> >::_Reserve (0141140h)


А вот освобождение памяти обоих контейнеров перед выходом из scope:
    return 0;
00141083  lea         ecx,[floats]  
00141089  call        std::vector<int,std::allocator<int> >::_Tidy (01410C0h)  
0014108E  lea         ecx,[ints]  
00141091  call        std::vector<int,std::allocator<int> >::_Tidy (01410C0h)
Re[17]: «Собаку съел»
От: samius Япония http://sams-tricks.blogspot.com
Дата: 24.01.17 16:59
Оценка:
Здравствуйте, alex_public, Вы писали:

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


_>Безусловно. Поэтому если мы будем говорить о коде, реализованном на базе механизма явной специализации шаблонов (http://en.cppreference.com/w/cpp/language/template_specialization), то это будет именно ad hoc полиморфизм. Это механизм конечно же тоже широко применяется в C++ коде, но до распространённости классического применения шаблонов ему очень далеко.

Ок

_>Если же говорить о классическом применение шаблонов (типа контейнеров STL), то для программиста это безусловно является параметрическим полиморфизмом. Хотя бы потому, что программист пишет ровно одну версию кода для всех типов.

Этот тезис уже не касается стандартной equal_to, т.к. одну версию для всех типов он не держит. Без специализации equal_to работает лишь для ограниченного количества типов и всегда найдется тип, для которого equal_to не работает "из коробки".

_>А то, что компилятор там потом из соображений оптимизации может размножать эти версии кода, это уже дело десятое и на структуру кода не влияет. Это кстати можно легко увидеть с помощью простейшего мысленного эксперимента: если допустим поменять компилятор C++ так, чтобы он реализовывал шаблоны например по механизму параметрического полиморфизма Хаскеля, то весь классический шаблонный код продолжит спокойно работать без всяких изменений (ну разве что медленным станет, как Хаскель).

Мысленный эксперимент в баню, мы ведь говорим о конкретном языке C++, а не о сферовакуумном H++.
Я предлагаю обратиться к источнику классификации:

Ad-hoc polymorphism, by contrast, allows a polymorphic value to exhibit different behaviors when “viewed” at different types. The most common example of ad-hoc polymorphism is overloading, which associates a single function symbol with many implementations; the compiler (or the runtime system, depending on whether overloading resolution is static or dynamic) chooses an appropriate implementation for each application of the function, based on the types of the arguments.

TAPL

(жаль, что он в повествовательно-лирической форме, а не в формально строгой)

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

Several varieties of polymorphism can be found in modern languages (this classification comes from Strachey, 1967, and Cardelli and Wegner, 1985).

Там же

Если не согласен — приводи свою классификацию и желательно с источником.

_>Конечно же equal_to является всего лишь обёрткой вокруг оператора равенства, предназначенная для более удобной и краткой передачи данного простейшего предиката в различные алгоритмы библиотеки. Но сам факт возможности написания данной обёртки является очевидным проявлением работы механизма параметрического полиморфизма.

неа (см выше)

_>Если очень хочется увидеть подобный компаратор, не являющийся просто обёрткой вокруг какого-то одного оператора, а привносящий какую-то логику, то есть варианты гораздо проще. Например так:

_>
_>bool operator()(const T &lhs, const T &rhs) const
_>{
_>    return lhs.compare(rhs)==0;
_>}
_>

И что, это работает для всех типов, или только для тех, у которых определен инстанс метод compare?

_>Но на самом деле все эти дополнительные доказательства уже не нужны, т.к. уже та самая простейшая обёртка является очевидным представителем параметрического полиморфизма — работает для многих типов и при этом в исходных кодах ровно одна реализация.

Что значит "для многих типов"? Формально нужна работа для всех типов. И одна реализация для всех, так, что бы даже компилятор и рантайм не нуждались в указании нужной реализции.

_>И так, подводя итоги:

_>1. equal_to — компаратор.
_>2. работает с разными типами — полиморфный.
_>3. имеет одну реализацию для всех типов — параметрический.
пожалуй, я найду тип, для которого стандартная реализация не работает. Точнее, мешает скомпилироваать проект.

_>4. реализован через шаблоны — инлайнится.

_>5. находится в стандартной библиотеке языка — нужен.
_>

_>P.S. Ну а вообще я конечно не совсем корректно влез со своим C++ в вашу дискуссию. Вы то говорили про C# и там все твои аргументы были безусловно верными.

да ладно
Re[16]: «Собаку съел»
От: Sinix  
Дата: 24.01.17 17:06
Оценка: 1 (1)
Здравствуйте, alex_public, Вы писали:

Коротко — +1.

Длиннее:

S>>"с отказом от части контрактов в плане оптимизаций дотнет принципиально ничем не отличается от нативного кода".

_>Тоже верно, но с одной существенной натяжкой. Для получения быстродействия, сравнимого с C/C++, программисту обязательно придётся активно использовать unsafe код, непосредственную работу с памятью и стеком, хорошо знать тонкости работы процессора и т.п.

Кесарю — кесарево

В смысле, никто не запрещает сделать вставки на сях (для .native и blittable типов интероп хорошо так ускорен, практически бесплатен). Для бесплатного маршаллинга сложных структур данных будет Memory<T> — тот же массив, только поверх произвольной области памяти процесса, в т.ч. unmanaged. Ну, т.е. чисто теоретически особых проблем нет.

На практике Memory<T> сейчас нет — раз, .net native практически нигде нет — два и программист в любом случае будет обязан иметь высокую квалификацию — три. Ну, т.е. особого чуда не будет. Главный бонус — шарп позволит в обмен на больше усилий выжимать больше производительности.


_>Т.е. не получится фокуса, что мы просто перекомпилируем стандартный код на C# под .net native и если он заведётся (не использует всякие нехорошие рефлексии и т.п.), то автоматически получим быстродействие C/C++.


Ты забыл указать _какого_ C/C++
Если среднестатистического — то шансы таки есть. В смысле, с разницей в несколько десятков процентов, а не в разы. Т.к. по сути .net native — бэкенд от MS c++ compiler (ну, что есть, да) + урезанный рантайм дотнета. Загвоздка в качестве генерации AST, который скармливают этому бэкенду и совместимости оптимизаций с рантаймом .net core. Обе части допиливают, но прогресс пока не впечатляет.

Если речь про что-то узкоспециализированное, особенно с жёсткими ограничениями по latency — ну... без меня.


S>>* когда аналог .native будет доступен для прочих форков дотнета (ориентировочно — через релиз).

_>А разве где-то вообще заявлялось, что будет движение в этом направление? )
Угу

Остальное поскипал, т.к. согласен.
Re[16]: «Собаку съел»
От: samius Япония http://sams-tricks.blogspot.com
Дата: 24.01.17 17:10
Оценка: +2
Здравствуйте, vdimas, Вы писали:

V>К сожалению, первые 8 лет — вообще не туда. Дотнет был разработан полупрофессиональными программистами, полуинженерами. Почти нубами. Это не попытка наезда, это медицинский факт. Эти люди получили почти безграничный кредит доверия на волне той самой шумихи "ява в интернете". Они оказались неспособны рассмотреть вопросы организации вычислений в комплексе, не смогли промоделировать реальные пути развития вычислительных сугубо программных технологий. Сам проект дотнета "выстрелил" лишь благодаря фантастическим потраченным на проект человекочасам в сочетании с, скажем прямо, недостижимым авторитетом MS на начало 2000-х.


У меня вопросы: где были полноценные (не полу-) профессионалы и инженеры? Что они создали за это время, что смогли промоделировать, на что равняемся?
Re[17]: «Собаку съел»
От: vdimas Россия  
Дата: 24.01.17 17:49
Оценка: 2 (1)
Здравствуйте, Sinix, Вы писали:

_>>А разве где-то вообще заявлялось, что будет движение в этом направление? )

S>Угу

Прикольно.
Кстате, в MS компиляторе С++ в последних версиях происходят натуральные чудеса — мне порой СЛОЖНО добиться ситуации, чтобы в релизе виртуальные методы вызывались именно как виртуальные — в большинстве случаев комплятор "видит" конкретный тип, созданный "где-то ранее" и диспатчит прямые вызовы.

Схематично ситуация:
class Base {
  typedef SomeType value_type;
  value_type value_;

  virtual void update(value_type newValue) {
    if(value_ != newValue) {
      value_ = newValue;
      onValueChanged();
    }
  }

  virtual void onValueChanged(SomeType newValue) {}
};

template<typename T>
class SomeAspect : public T
{
  typedef T base;
  typedef typename T::value_type value_type;

  virtual void onValueChanged(value_type newValue) {
    someLog(newValue);
    base::onValueChanged(newValue);
  }
};


Есть несколько похожих Base, некоторые образуют иерархию, где метод-аналог update — виртуальный. Внутри виртуального update по условию вызывается другой виртуальный метод. Так вот. В релизе метод update вызывается напрямую или инлайнится. Аналогично не наблюдается ни одного виртуального вызова onValueChanged (через vtable) — всегда идёт прямой вызов метода наследника. При том, что сами аспекты могут наворачиваться друг на друга, т.е. может быть более одного наследника — пофик, вызовется самый нижний.
Re[42]: benchmark
От: IID Россия  
Дата: 24.01.17 18:39
Оценка:
Здравствуйте, itslave, Вы писали:

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


Враньё же. Андроид почти весь нативный. И телефония, и сеть, и системные сервисы, и отрисовка. Жаба там только для склейки логики. Эдакий скриптовый клей, типа LUA в играх. И то хватало для тормозов и жора памяти. Что бедный гугл аж ART запилил в двух реинкарнациях, чтобы жабу пре-джитить в нативный код, так как MS делает в винфонах с рождения.
kalsarikännit
Re[45]: Visual C# vs C++. Надо сравнить перспективы.
От: IID Россия  
Дата: 24.01.17 19:21
Оценка:
Здравствуйте, alexzzzz, Вы писали:

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


A>>>Честно говоря, я не очень понимаю, зачем среднестатистическому шутеру C++. В них нагрузка больше на графику, чем на игровую логику. Тут скорее С++ нужен не для шутеров, а просто для движков.

_>>Я вот тоже не очень понимаю зачем в автомобилях нужен металл. Он же ведь используется всего лишь для рамы, двигателя, передачи и т.п. А для кресел то нужна в основном кожа!

A>Объясняю: двигатель (1шт) невозможно переиспользовать, у движка же это основное предназначение.


Это ещё почему ?
Один и тот же двигатель ставится в целую кучу автомобилей. А когда автомобиль доживает свой век — двигатель вытаскивается и идёт на замену поломанным(контрактный)/на запчасти/вкорячивается в разные лютые самоделки.
kalsarikännit
Re[18]: «Собаку съел»
От: alex_public  
Дата: 24.01.17 21:42
Оценка: 3 (1)
Здравствуйте, samius, Вы писали:

_>>Если же говорить о классическом применение шаблонов (типа контейнеров STL), то для программиста это безусловно является параметрическим полиморфизмом. Хотя бы потому, что программист пишет ровно одну версию кода для всех типов.

S>Этот тезис уже не касается стандартной equal_to, т.к. одну версию для всех типов он не держит. Без специализации equal_to работает лишь для ограниченного количества типов и всегда найдется тип, для которого equal_to не работает "из коробки".

Стандартная equal_to работает для всех типов, для которых определён оператор равенства. Точно так же как и какой-нибудь vector<T> работает не для всех типов, а только для имеющих (как минимум) конструктор и оператор перемещения. Так что не пойму где ты тут увидел разницу с контейнерами STL.

_>>А то, что компилятор там потом из соображений оптимизации может размножать эти версии кода, это уже дело десятое и на структуру кода не влияет. Это кстати можно легко увидеть с помощью простейшего мысленного эксперимента: если допустим поменять компилятор C++ так, чтобы он реализовывал шаблоны например по механизму параметрического полиморфизма Хаскеля, то весь классический шаблонный код продолжит спокойно работать без всяких изменений (ну разве что медленным станет, как Хаскель).

S>Мысленный эксперимент в баню, мы ведь говорим о конкретном языке C++, а не о сферовакуумном H++.
S>Я предлагаю обратиться к источнику классификации:

Ууу) Ты всё же решился свернуть на эту холиварную тему. Вопрос о сути шаблонов C++ уже давно является известной темой для споров. И на этом форуме и на других известных. Повторять все эти потоки флейма нет никакого желания — это всё можно найти на форуме самостоятельно. Так что просто выскажу своё итоговое мнение по данному вопросу, в сравнение с тем же Хаскелем:

У C++ есть параметрический полиморфизм на уровне исходного кода и нет никакого полиморфизма (ну кроме банальных виртуальных функций) на уровне машинного кода (и поэтому он работает быстро).

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

Основная цель всего этого механизма в том, чтобы облегчить работу программиста, позволив ему писать один код для всех случаев. Шаблоны из C++ это полностью реализуют. А с учётом ещё и вопроса производительности данное решение выглядит на голову лучше всех остальных реализаций. Ценой же этого (ну никогда не бывает идеала и у всех мощных технологий есть обратная сторона) являются большие сложности с введением в язык модулей.

_>>Если очень хочется увидеть подобный компаратор, не являющийся просто обёрткой вокруг какого-то одного оператора, а привносящий какую-то логику, то есть варианты гораздо проще. Например так:

_>>
_>>bool operator()(const T &lhs, const T &rhs) const
_>>{
_>>    return lhs.compare(rhs)==0;
_>>}
_>>

S>И что, это работает для всех типов, или только для тех, у которых определен инстанс метод compare?

Для всех типов, у которых определена функция-член compare.

_>>Но на самом деле все эти дополнительные доказательства уже не нужны, т.к. уже та самая простейшая обёртка является очевидным представителем параметрического полиморфизма — работает для многих типов и при этом в исходных кодах ровно одна реализация.

S>Что значит "для многих типов"? Формально нужна работа для всех типов.

С чего бы это? Откуда такое бредовое требование? Да ещё и формальное... )))

Т.е. если я напишу на Хаскеле функцию f вида "f a = xrmbrm a", то она по твоему обязательно будет работать для всех типов? ))) Или быть может в Хаскеле тоже нет параметрического полиморфизма? )))

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


Ну это уже как раз тот самый спорный вопрос (см. выше).

_>>И так, подводя итоги:

_>>1. equal_to — компаратор.
_>>2. работает с разными типами — полиморфный.
_>>3. имеет одну реализацию для всех типов — параметрический.
S>пожалуй, я найду тип, для которого стандартная реализация не работает. Точнее, мешает скомпилироваать проект.

И? ) Это как-то влияет на аргументацию? )
Re[17]: «Собаку съел»
От: alex_public  
Дата: 24.01.17 22:11
Оценка: +1
Здравствуйте, Sinix, Вы писали:

S>Главный бонус — шарп позволит в обмен на больше усилий выжимать больше производительности.


Согласен. Ну во всяком случае на данный момент оно видится так. А в будущем посмотрим, как оно окажется на практике (а то у MS же периодически случаются реализации "как всегда").

S>>>* когда аналог .native будет доступен для прочих форков дотнета (ориентировочно — через релиз).

_>>А разве где-то вообще заявлялось, что будет движение в этом направление? )
S>Угу

По ссылке больше рассуждений о том, как реализовать работу .net core для тех платформ, для которых нет работающего RyuJIT. И предлагается решение в виде компиляции этого подмножества .net в C++, с дальнейшей компиляцией родным для платформы компилятором C++. Это всё конечно же тоже интересно, но я не увидел там утверждения о планах перевода "взрослого" .net'а на нативные рельсы и т.п.
Re[19]: «Собаку съел»
От: samius Япония http://sams-tricks.blogspot.com
Дата: 24.01.17 22:43
Оценка:
Здравствуйте, alex_public, Вы писали:

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


S>>Этот тезис уже не касается стандартной equal_to, т.к. одну версию для всех типов он не держит. Без специализации equal_to работает лишь для ограниченного количества типов и всегда найдется тип, для которого equal_to не работает "из коробки".


_>Стандартная equal_to работает для всех типов, для которых определён оператор равенства. Точно так же как и какой-нибудь vector<T> работает не для всех типов, а только для имеющих (как минимум) конструктор и оператор перемещения. Так что не пойму где ты тут увидел разницу с контейнерами STL.

Не знаю, откуда ты взял, что я увидел разницу с контейнерами STL. Я ведь не написал об этом? Согласно классификации, которую я привел (и которую ты проигнорировал), vector<T> — ad hoc.

S>>Я предлагаю обратиться к источнику классификации:


_>Ууу) Ты всё же решился свернуть на эту холиварную тему. Вопрос о сути шаблонов C++ уже давно является известной темой для споров. И на этом форуме и на других известных. Повторять все эти потоки флейма нет никакого желания — это всё можно найти на форуме самостоятельно. Так что просто выскажу своё итоговое мнение по данному вопросу, в сравнение с тем же Хаскелем:

Прости, но твое итоговое мнение основано на какой именно классификации?

_>Основная цель всего этого механизма в том, чтобы облегчить работу программиста, позволив ему писать один код для всех случаев. Шаблоны из C++ это полностью реализуют. А с учётом ещё и вопроса производительности данное решение выглядит на голову лучше всех остальных реализаций. Ценой же этого (ну никогда не бывает идеала и у всех мощных технологий есть обратная сторона) являются большие сложности с введением в язык модулей.

Ну причем тут производительность? Каким образом производительность C++ влияет на классификацию?

S>>И что, это работает для всех типов, или только для тех, у которых определен инстанс метод compare?


_>Для всех типов, у которых определена функция-член compare.

Вот видишь?

_>>>Но на самом деле все эти дополнительные доказательства уже не нужны, т.к. уже та самая простейшая обёртка является очевидным представителем параметрического полиморфизма — работает для многих типов и при этом в исходных кодах ровно одна реализация.

S>>Что значит "для многих типов"? Формально нужна работа для всех типов.

_>С чего бы это? Откуда такое бредовое требование? Да ещё и формальное... )))


Я думаю что к нему можно прийти отсюда:

Parametric polymorphism, the topic of this chapter, allows a single piece of code to be typed “generically,” using variables in place of actual types, and then instantiated with particular types as needed. Parametric definitions are uniform: all of their instances behave the same.

TAPL


А откуда требование "для многих"?

_>Т.е. если я напишу на Хаскеле функцию f вида "f a = xrmbrm a", то она по твоему обязательно будет работать для всех типов? )))

может быть и для всех, если у нас "xrmbrm = id"
а может и не для всех. Она возьмет ограничения из определения xrmbrm

_>Или быть может в Хаскеле тоже нет параметрического полиморфизма? )))

Есть параметрический. Но есть и ad hoc. И я догадываюсь, как один отличить от другого.

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


_>Ну это уже как раз тот самый спорный вопрос (см. выше).

Конечно тот же самый. Какую классификацию ты используешь?

_>>>И так, подводя итоги:

_>>>1. equal_to — компаратор.
_>>>2. работает с разными типами — полиморфный.
_>>>3. имеет одну реализацию для всех типов — параметрический.
S>>пожалуй, я найду тип, для которого стандартная реализация не работает. Точнее, мешает скомпилироваать проект.

_>И? ) Это как-то влияет на аргументацию? )

что именно здесь не очевидно? если найдется тип, для которого equal_to требует специального уточнения (в исходниках), то это ad hoc (как минимум на уровне исходников), если ты предлагаешь подразделять полиморфизм исходников от полиморфизма исполняемого кода.
Re[18]: Бинарная склейка
От: Qbit86 Кипр
Дата: 24.01.17 23:33
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Вот простой пример


Не наблюдаю такого в отладчике после лёгкой модифиации кода:
#include <vector>

int main()
{
    std::vector<char> chars;
    std::vector<double> doubles;

    chars.push_back(1);
    doubles.push_back(1);

    return 0;
}


    chars.push_back(1);
00CE107B  push        eax  
00CE107C  lea         ecx,[chars]  
00CE107F  mov         byte ptr [ebp-29h],1  
00CE1083  call        std::vector<char,std::allocator<char> >::emplace_back<char> (0CE12F0h)  
    doubles.push_back(1);
00CE1088  movsd       xmm0,mmword ptr [__real@3ff0000000000000 (0CE31A8h)]  
00CE1090  lea         eax,[ebp-34h]  
00CE1093  push        eax  
00CE1094  lea         ecx,[doubles]  
00CE1097  movsd       mmword ptr [ebp-34h],xmm0  
00CE109C  call        std::vector<double,std::allocator<double> >::emplace_back<double> (0CE1220h)


Q>>Что упущено; из-за чего эффект от оптимизации распухания кода незаметен?

V>Упущена стадия релизной кодогенерации конечного бинарного образа.

Подожди. Для меня как автора библиотеки полученный lib-файл — и есть конечный бинарный образ. Дальше я его поставляю прикладному программисту, а он уже линкует. И указанный lib-файл пухнет. Я не вижу тут проявления упомянутого «это позволяет бороться с распуханием кода после применения шаблонов».

То, что такая оптимизация существует, я не спорю. Только я очень скептически отношусь к тому, что она хоть сколь-нибудь заметно влияет на code bloat. В /cpp.applied как раз недавно обсуждение было на примере OpenCV, где с распуханием борятся ручным стиранием типов, не возлагая надежд на «бинарную склейку»: http://rsdn.org/forum/cpp.applied/6676361
Автор: jazzer
Дата: 24.01.17
Глаза у меня добрые, но рубашка — смирительная!
Re[18]: «Собаку съел»
От: Sinix  
Дата: 25.01.17 05:32
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Согласен. Ну во всяком случае на данный момент оно видится так. А в будущем посмотрим, как оно окажется на практике (а то у MS же периодически случаются реализации "как всегда").

Ой, не напоминай. Нам этим пользоваться.

_>По ссылке больше рассуждений о том, как реализовать работу .net core для тех платформ, для которых нет работающего RyuJIT. И предлагается решение в виде компиляции этого подмножества .net в C++, с дальнейшей компиляцией родным для платформы компилятором C++. Это всё конечно же тоже интересно, но я не увидел там утверждения о планах перевода "взрослого" .net'а на нативные рельсы и т.п.


Ну да, это чисто обзорный пост. Смысл — наличие нескольких pipelines (llillc (llvm); il2cpp от unity; RyuJit AOT; .net native), которые можно будет использовать для трансляции в натив. Понятно, что в финал пройдут не все, но наличие запасных радует.
Про перенос на взрослый .net — сейчас .core становится портом части библиотек дотнета под все платформы, а не форком, как изначально задумано. Т.е. c обратным переносом дела всё легче и легче обстоят.
Про перевод на нативные рельсы всего и сразу — не будет в обозримом будущем, ибо совместимость. Будет opt-in поведение: хочешь полноценный рантайм — вот тебе рантайм. Готов смириться с некоторыми ограничениями — вот тебе оптимизированный бинарник.
Re[19]: Бинарная склейка
От: romangr Россия  
Дата: 25.01.17 06:26
Оценка:
Здравствуйте, Qbit86, Вы писали:

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


V>>Вот простой пример


Q>Не наблюдаю такого в отладчике после лёгкой модифиации кода:

Q>
#include <vector>

Q>int main()
Q>{
Q>    std::vector<char> chars;
Q>    std::vector<double> doubles;

Q>    chars.push_back(1);
Q>    doubles.push_back(1);

Q>    return 0;
Q>}


Q>
    chars.push_back(1);
Q>00CE107B  push        eax  
Q>00CE107C  lea         ecx,[chars]  
Q>00CE107F  mov         byte ptr [ebp-29h],1  
Q>00CE1083  call        std::vector<char,std::allocator<char> >::emplace_back<char> (0CE12F0h)  
Q>    doubles.push_back(1);
Q>00CE1088  movsd       xmm0,mmword ptr [__real@3ff0000000000000 (0CE31A8h)]  
Q>00CE1090  lea         eax,[ebp-34h]  
Q>00CE1093  push        eax  
Q>00CE1094  lea         ecx,[doubles]  
Q>00CE1097  movsd       mmword ptr [ebp-34h],xmm0  
Q>00CE109C  call        std::vector<double,std::allocator<double> >::emplace_back<double> (0CE1220h)


У char и double размер разный, а у float и int одинаковый.
Поэтому и код для float-int одинаковый, а для char-double разный.
... << RSDN@Home (RF) 1.2.0 alpha 5 rev. 67>>
Re[20]: Размер разный
От: Qbit86 Кипр
Дата: 25.01.17 06:31
Оценка:
Здравствуйте, romangr, Вы писали:

R>У char и double размер разный, а у float и int одинаковый.

R>Поэтому и код для float-int одинаковый, а для char-double разный.

Да это понятное дело.
Глаза у меня добрые, но рубашка — смирительная!
Re[19]: Бинарная склейка
От: vdimas Россия  
Дата: 25.01.17 11:10
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Не наблюдаю такого в отладчике после лёгкой модифиации кода:

Q> std::vector<char> chars;
Q> std::vector<double> doubles;

А действительно ли тебе требуется объяснение от другого человека, почему так?


Q>>>Что упущено; из-за чего эффект от оптимизации распухания кода незаметен?

V>>Упущена стадия релизной кодогенерации конечного бинарного образа.
Q>Подожди. Для меня как автора библиотеки полученный lib-файл — и есть конечный бинарный образ.

Этот образ не предназначен для исполнения.


Q>Дальше я его поставляю прикладному программисту, а он уже линкует.


В этом месте вся магия и происходит.


Q>И указанный lib-файл пухнет.


Пусть.


Q>Я не вижу тут проявления упомянутого «это позволяет бороться с распуханием кода после применения шаблонов».


Упорно не туда смотришь. Еще и настаиваешь на своём праве смотреть не туда. ))
Можно я сделаю вид, что ты этого не спрашивал?


Q>То, что такая оптимизация существует, я не спорю. Только я очень скептически отношусь к тому, что она хоть сколь-нибудь заметно влияет на code bloat.


Когда шаблоны только появились, конечный код распухал многократно.
Собсно, без такой "склейки" техника шаблонов не обрела бы нынешней популярности.


Q>В /cpp.applied как раз недавно обсуждение было на примере OpenCV, где с распуханием борятся ручным стиранием типов, не возлагая надежд на «бинарную склейку»: http://rsdn.org/forum/cpp.applied/6676361
Автор: jazzer
Дата: 24.01.17


Трюк по ссылке близок к парадигме pIml — чтобы не тащить в h-файлы подробности приватного устройства типов и списка процедур по их обработке.

К тому же, обсуждаемая библиотека кроссплатформенная, а не во всех компиляторах С++ наблюдается современный уровень оптимизаций.
Re[20]: Границы применения
От: Qbit86 Кипр
Дата: 25.01.17 11:55
Оценка: :)
Здравствуйте, vdimas, Вы писали:

Q>>Не наблюдаю такого в отладчике после лёгкой модифиации кода:

Q>> std::vector<char> chars;
Q>> std::vector<double> doubles;

V>А действительно ли тебе требуется объяснение от другого человека, почему так? ;)


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

V>Этот образ не предназначен для исполнения.

Q>>Дальше я его поставляю прикладному программисту, а он уже линкует.
V>В этом месте вся магия и происходит.

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

Q>>И указанный lib-файл пухнет.

V>Пусть.

Okay.
Глаза у меня добрые, но рубашка — смирительная!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.