Мой вопрос был вопросом сугубо любопытствующего обывателя (в данной сфере). Поэтому зачем так усложнять, достаточно было двух-трех строчного ответа. Но если это вдруг внезапно секрет — я не обижусь. :)
Да, представьте себе — у процессора много регистров SP. И много стеков. Один регистр SP и один стек — это реальный режим, его перестали использовать до того, как большинство посетителей Хабре родились…
Правильно ли я вас понимаю, что вы говорите не о переключаемых контекстах, а прямиком о нескольких hardware регистрах E®SP в x86/64?
Можно ссылку на эту информацию?
Спасибо, достаточно понятно объяснили, хотя реальная применимость мне пока туманна.
Важным преимуществом ФП является параллелизм. Поскольку все функции для вычислений используют только свои параметры, можно организовать вычисление независимых функций в произвольном порядке или параллельно, на результат вычислений это не повлияет. Следование элементам ФП-парадигмы упрощает построение многозадачности (в т.ч. для hardware см. read-only, оно же immutability).
Вот допустим хотим мы смоделировать покупателя.
Это уже дальнейший вопрос, как моделируется предметная область.
1. Функции в ФП устанавливают отношение (relationship). Эмфазис ФП — трансформация значений/данных.
2. Функциональные языки часто гибридные (Object-Functional) — например OCaml, Scala.
совершенно не понимаю, как в ФП реализуется что-то асинхронное, завязанное на время, возникающее от случая к случаю…
«асинхронное, завязанное на время, возникающее от случая к случаю» — назовем это Discrete Event Processsing / Discrete Event Model.
Обработка событий — это область все же ортогональная к парадигме программирования. Это можно понять задавшись вопросом — как это представимо для других парадигм: ООП, процедурной на ЯВУ или таблицы прерываний с обработчиками на ассемблере. Тем не менее, смысл в этом замечании есть, поскольку классически под моделирование систем с дискретными событиями был создан именно ООП (Simula), а вот характерные для ФП relationship,transformation служат для решения задач в другом пространстве. Но так дело выглядит при первом взгляде. Когда же речь заходит о потоках событий, сигналах, и потоковой асинхронной обработке вообще — на сцене быстро появляется ФП. Сугубо практическое применение этому — Matlab и его Simulink.
А еще такой вопрос, глядя на машинный код ФП программы, вы сможете отличить его от кода, полученного компиляцией с императивного языка?
Я это понял как вопрос о парадигме, а не о языках, компиляторах и какие они порождают финальные исполняемые файлы. Императивное и функциональное представление эквивалентны (доказано теоретически). ФП лишь парадигма, также как ООП может быть заменено программированием в процедурном стиле (C++ программа в некоторых компиляторах претерпевает фазу превращения в C. На последнем можно вручную симулировать наследование и виртуальные методы). С другой стороны, при применении почерпнутых техник ФП к обычным программам можно увидеть некоторые архитектурные отличия. К примеру, посреди тела функции не будет обращения или модификации каких-либо переменных. Передача аргументов, возврат значений будет преимущественно by value, при этом можно будет заметить что переданные аргументы (втч данные по указателям/ссылкам) не модифицируются. Будет заметна однократная инициализация без пере-присваивания. Повторюсь, это в самом общем, генеральном смысле, не погружаясь в явные отличия которые порождают компиляторы и их оптимизации.
Как я понимаю, это перевод блога, так что воспринимать это серьезно не стоит. Но это хороший пример запутавшегося человека, слабо понимающего чем он занимается. Это я вам как учёный пишу. И для того чтобы такое написать, у этого человека есть некоторые причины.
Наука это род деятельности для выработки и систематизации объективных знаний.
Знание нам необходимо для практической пользы, оно помогает как объяснить в окружающем мире последствия тех или иных причин, так и подобрать причины под желаемые последствия.
Такова цель науки. Если знание объясняет окружающий мир, имея тем самым точку приложения — оно проходит проверку. Если знание ничего не объясняет (или в этом невозможно убедиться) будучи бездоказательным — оно бесполезно, бессмысленно.
Таким образом, те самые искомые «доказательства» в науке еще как есть — это объективные критерии, лежащие в окружающем мире.
Можно понять, почему этот человек впал в отчаяние. Он астрофизик. Новейшая астрофизика, в особенности её теоретические разделы, действительно, не имеет доказательств (т.к. мы не можем слетать к её объектам) и кроме того, мало где применима.
А вот большинство отделов математики, вопреки ожиданиям, очень даже связаны с реальностью (скажем, микроархитектура Canon Lake имеет практические команды GF2P8AFFINE* работы в полях Галуа — это имеет практическую применимость и отражает окружающий мир). С другой стороны, неевклидовы геометрии, как раз, практически не употребимы и непроверяемы, являясь чистой спекуляцией.
Боюсь, у него вдобавок ко всему, как и у многих моих оппонентов-теоретиков классический «перевёртыш». Он отвергает доказательную и применимую классику, считая основой спекулятивные теории.
Ну и наконец, насчет Фейнмана.
Надо бы посмотреть весь контекст беседы. Но я опять, подозреваю что тут передёрнуто. Скорее всего, имеется в виду не то, что мы ни в чем вообще не уверены и не можем быть уверены (нет доказательств, etc..) А то, что никакое знание не является абсолютным, но всегда лишь приближением.
Функциональное Программирование (ФП) можно представить себе как такое написание программы, когда ее выполнение представляет собой как бы вложенные друг за другом «математические функции»: fun1(fun2(fun3(x))) У каждой функции есть совершенно чёткий «вход» и совершенно чёткий «выход», также как у математических (вычислительных) функций: Выход = function(Вход). При этом ни одна функция внутри не обращается к каким-либо переменным/памяти/портам/итд, короче ко всему тому, что представляет собой состояние/память. Подобное состояние, если оно есть (к примеру порт), подается только как «вход». И вдобавок к этому функция должна быть детерминирована (делать одно и то же).
Что это даёт? Подобные функции не зависят ни от чего, кроме как своих входных параметров. И поэтому, если каждый раз перезапускать их с одними и теми же аргументами, мы будем получать на выходе один и тот же результат.
Эмбедщику можно это понять так, что данные словно бы передаются в регистрах, и в регистрах же возвращаются назад, ничего более не меняя.
Это очень удобно и для отладки и для написания стабильных программ — проблемы отладки чаще всего заключаются в том что при работе программы меняется какое-то внутреннее состояние (память, переменные, стек итд) и нет возможности сделать «шаг назад». А при ФП парадигме — достаточно подать на «вход» программы одни и те же предварительно записанные данные, и она выдаст один и тот же результат, пока мы не поправим саму программу.
Парадигма такова, что программа как бы «воздействует» на проходящие через нее данные или их потоки, сама же являя собой «чистый закон».
Что интересно, правильная и рекомендуемая методология *NIX программирования это, в некотором смысле, ФП: мелкие отдельные утилиты, каждая выполняющая свою функцию, принимающие данные на вход, и выдающие детерминированно одно и то же, при том что их можно объединять друг за другом, т.е. выход одной утилиты/команды по-цепочке передавать на вход другой.
Пиксельные шейдеры тоже при определенном приближении являют собой ФП-стиль, вместе с реактивным.
Часть существующих программ и так уже написана приближаясь к функциональному стилю.
Реальное ФП, конечно, подразумевает собой гораздо большее, но кое-какие полезные элементы почерпнуть из ФП, как видим, можно.
Скажу страшное, рискую не понравиться.
… Мои размышления привели к тому, что по-большому счету, работа современных программистов-разработчиков тоже бессмысленна. Она обладает «смыслом» в очень коротком временном промежутке. Это как сервис. Мы неустанно постоянно делаем одно и то же, и не замечаем это.
Где все те чудесные программы 80х и 90х? Где все прекрасные фреймворки? Библиотеки? (Читали «Design Patterns» — книжку из 90х? Обратили внимание, сколько прекрасных фреймворков там упомянуто? Десятки...) Где замечательные монбланы кода браузера Opera? Материки операционной системы OS/2? Тонны софта Amiga или Mac? Кто сейчас помнит о списке «3D engines list» со списком из 643 проектов? http://cg.cs.tu-berlin.de/~ki/engines.html Где кодовые базы десятков тысяч игр? А сколько движков сайтов или внутри-конторных базочек ушло на свалку истории? Представить страшно. А все еще только впереди — в последние 5-7 лет произошла сильная фрагментация. Сколько сейчас пишется кода на скриптовых, интерпретируемых и динамических JS, Go, Python, Ruby, PHP, Erlang… Десятки языков. Нет, я не пессимизирую, понятно что информационная сфера эфемерна и строго говоря, абстрактна. Но когда результаты человеческого труда живут 3-5 лет, а то и предназначены для развлечения, чтоб мелькнуть и забыть — что-то реально идет не так… Не задумывались об этом?
Здесь таится ловушка. Дело в том, что конверсия «null pointer constant» в указатель в стандарте оговорена отдельно, при этом для финального значения конверсии (т.е. значения указателя) не гарантируется битовое значение «все нули». Вместо этого указывается что это implementation-defined.
Что же касается «Про x и bar»
#include <iostream>
int x = 0;
int bar(int(x));
int main() {
std::cout << bar;
}
Не все так просто, как это написал автор. Это «хак» Weak symbol GCC и ELF, стандарт его (имхо) не оговаривает. С компилятором Visual C++ дело окончится ошибкой линкера «unresolved external symbol».
Здесь существует еще один скрытый фактор, осмысленный по-видимому не до конца. Google — очень большая компания с большим количеством подразделений и проектов. И на самом деле для успеха большое значение имеет над чем именно ты работаешь. Имеет значение команда, проект, подразделение.
Будучи «разменной монетой» и работая в «низах», на посредственных, бросовых проектах, которые в реальности не несут ключевую технологию компании, ты предсказуемо столкнешься с трудностями должностного роста. Сие есть закономерность, ее необходимо осмыслить и запомнить.
Всё так и есть, почему я и говорю,
я тоже не знаю одного универсального способа избавления от проверок в коде и тоже считаю что ситуация что и где использовать это гибкий вопрос.
p.s. коммент не просмотрите про буфер в паскале: ссылка
«Обёртка» — она, как бы, «оборачивает». То есть вызывает стандартную функцию malloc, но дополнительно что-то как-то обрабатывает.
Chromium же заменяет malloc целиком и полностью: его malloc является полной заменой: функции имеют названия не chromium_malloc и chromium_free, а просто malloc и free, все библиотеки, влинкованные в Chromium используют именно их, а стандартные функции — не используются вообще.
Есть разница между «обёрткой» и вот этим, а? Или таки нет? Или вам что в лоб, что по лбу?
1. Chromium меня не интересует. Если я его и упомянул, то только чтобы сказать что он «набор процессов», какой в нем malloc мне в текущем контексте вообще без разницы.
Поэтому смысла мне писать об этом ноль. В моей основной теме Chromium никак не звучал.
2. Про механизм malloc hooks в GLBC я в курсе, как и POSIX dlsym.
3. Теперь насчет «обертки», как это я понимал, когда произносил вам определенные слова выше и связывал их с memory manager.
«Обертка» оборачивает вызов к malloc'у().
Вы называете ее как-нибудь my_malloc().
Ваш код зовет везде my_malloc()
Эта обертка к malloc'у под названием my_malloc вызывает внутри себя malloc() и сразу «откусывает» блок памяти.
В самом примитиве — она вообще ничего не делает, это именно только функция обертка malloc(), все вызовы форвардятся malloc'у(), почему она так и называется, «обертка».
В самом сложном случае — внутри пишутся функции эдакого наколенного менеджера памяти для сишечки, то есть отожрала блок у malloc'а — раздает под видом my_malloc.
Нет. Я с самого начала сказал, что я не знаю одного универсального способа избавления от проверок в коде и, более того, считаю, что во многих случаях их использование меньшее зло
Я тоже не знаю одного универсального способа избавления от проверок в коде и тоже считаю что ситуация что и где использовать это гибкий вопрос.
Вот например знакомый вам язык C++, кроме старых версий MSVC библиотек (хотя это фиксится), архитектурно решает вопрос контролем не проверками по месту в коде, а глобальной проверкой выполненной в operator new и выкидывающей std::bad_alloc.
То есть, он реализует глобальную парадигму проверки аллокации памяти (а не по месту).
Также, как звучавшее предложение.
Это почему это, вдруг? Один мой хороший друг, только начинающий заниматься программированием не так давно задавал вопросы по поводу вот этого вот сайта.
Классика не умирает, и как Turbo Pascal 7.0, так и Turbo C/C++ 3.1 до сих пор в ходу в ВУЗах. А упомянул я не Turbo Pascal 7.0, а Turbo Pascal 6.0 — так это потому, что Turbo Vision именно в версии 6.0 появился, а не в 7.0
Его, если вам интересно, можно тут взять — и убедиться, что Turbo Vision и всё с ним связанное в нём уже есть…
Смеялся!
Извините, не распарсил все эти пространные рассуждения с увлечением какой есть паскаль и где его (вдруг!) можно взять.
Мдас. Как-то смешно у вас вышло.
Так я не понял, вы младше? Или старше?
Если младше, то видимо просто работа была не так давно? В каком году? BP/TP в 95ом заменила Delphi, я кстати на ней и писал.
У меня под боком в 2000 г. в банковской системе сидел товарищ на Clipper'е, ну так вы понимаете как мы его дразнили. Плывет по реке Клипер, на Клипере Шкипер, у Шкипера… :-)
Речь шла про x86/64.
Так один регистр стека хардварно, или нет?
Можно ссылку, откуда вы взяли информацию про несколько?
Правильно ли я вас понимаю, что вы говорите не о переключаемых контекстах, а прямиком о нескольких hardware регистрах E®SP в x86/64?
Можно ссылку на эту информацию?
— какова конфигурация, по сколько видеокарт стоит в одной машине?
— как происходит обсчет, каждая видеокарта считает отдельный кадр или как?
Какова скорость рендеринга, за сколько рендерится кадр?
Это уже дальнейший вопрос, как моделируется предметная область.
1. Функции в ФП устанавливают отношение (relationship). Эмфазис ФП — трансформация значений/данных.
2. Функциональные языки часто гибридные (Object-Functional) — например OCaml, Scala.
«асинхронное, завязанное на время, возникающее от случая к случаю» — назовем это Discrete Event Processsing / Discrete Event Model.
Обработка событий — это область все же ортогональная к парадигме программирования. Это можно понять задавшись вопросом — как это представимо для других парадигм: ООП, процедурной на ЯВУ или таблицы прерываний с обработчиками на ассемблере. Тем не менее, смысл в этом замечании есть, поскольку классически под моделирование систем с дискретными событиями был создан именно ООП (Simula), а вот характерные для ФП relationship,transformation служат для решения задач в другом пространстве. Но так дело выглядит при первом взгляде. Когда же речь заходит о потоках событий, сигналах, и потоковой асинхронной обработке вообще — на сцене быстро появляется ФП. Сугубо практическое применение этому — Matlab и его Simulink.
Я это понял как вопрос о парадигме, а не о языках, компиляторах и какие они порождают финальные исполняемые файлы. Императивное и функциональное представление эквивалентны (доказано теоретически). ФП лишь парадигма, также как ООП может быть заменено программированием в процедурном стиле (C++ программа в некоторых компиляторах претерпевает фазу превращения в C. На последнем можно вручную симулировать наследование и виртуальные методы). С другой стороны, при применении почерпнутых техник ФП к обычным программам можно увидеть некоторые архитектурные отличия. К примеру, посреди тела функции не будет обращения или модификации каких-либо переменных. Передача аргументов, возврат значений будет преимущественно by value, при этом можно будет заметить что переданные аргументы (втч данные по указателям/ссылкам) не модифицируются. Будет заметна однократная инициализация без пере-присваивания. Повторюсь, это в самом общем, генеральном смысле, не погружаясь в явные отличия которые порождают компиляторы и их оптимизации.
Наука это род деятельности для выработки и систематизации объективных знаний.
Знание нам необходимо для практической пользы, оно помогает как объяснить в окружающем мире последствия тех или иных причин, так и подобрать причины под желаемые последствия.
Такова цель науки. Если знание объясняет окружающий мир, имея тем самым точку приложения — оно проходит проверку. Если знание ничего не объясняет (или в этом невозможно убедиться) будучи бездоказательным — оно бесполезно, бессмысленно.
Таким образом, те самые искомые «доказательства» в науке еще как есть — это объективные критерии, лежащие в окружающем мире.
Можно понять, почему этот человек впал в отчаяние. Он астрофизик. Новейшая астрофизика, в особенности её теоретические разделы, действительно, не имеет доказательств (т.к. мы не можем слетать к её объектам) и кроме того, мало где применима.
А вот большинство отделов математики, вопреки ожиданиям, очень даже связаны с реальностью (скажем, микроархитектура Canon Lake имеет практические команды GF2P8AFFINE* работы в полях Галуа — это имеет практическую применимость и отражает окружающий мир). С другой стороны, неевклидовы геометрии, как раз, практически не употребимы и непроверяемы, являясь чистой спекуляцией.
Боюсь, у него вдобавок ко всему, как и у многих моих оппонентов-теоретиков классический «перевёртыш». Он отвергает доказательную и применимую классику, считая основой спекулятивные теории.
Ну и наконец, насчет Фейнмана.
Надо бы посмотреть весь контекст беседы. Но я опять, подозреваю что тут передёрнуто. Скорее всего, имеется в виду не то, что мы ни в чем вообще не уверены и не можем быть уверены (нет доказательств, etc..) А то, что никакое знание не является абсолютным, но всегда лишь приближением.
Что это даёт? Подобные функции не зависят ни от чего, кроме как своих входных параметров. И поэтому, если каждый раз перезапускать их с одними и теми же аргументами, мы будем получать на выходе один и тот же результат.
Эмбедщику можно это понять так, что данные словно бы передаются в регистрах, и в регистрах же возвращаются назад, ничего более не меняя.
Это очень удобно и для отладки и для написания стабильных программ — проблемы отладки чаще всего заключаются в том что при работе программы меняется какое-то внутреннее состояние (память, переменные, стек итд) и нет возможности сделать «шаг назад». А при ФП парадигме — достаточно подать на «вход» программы одни и те же предварительно записанные данные, и она выдаст один и тот же результат, пока мы не поправим саму программу.
Парадигма такова, что программа как бы «воздействует» на проходящие через нее данные или их потоки, сама же являя собой «чистый закон».
Что интересно, правильная и рекомендуемая методология *NIX программирования это, в некотором смысле, ФП: мелкие отдельные утилиты, каждая выполняющая свою функцию, принимающие данные на вход, и выдающие детерминированно одно и то же, при том что их можно объединять друг за другом, т.е. выход одной утилиты/команды по-цепочке передавать на вход другой.
Пиксельные шейдеры тоже при определенном приближении являют собой ФП-стиль, вместе с реактивным.
Часть существующих программ и так уже написана приближаясь к функциональному стилю.
Реальное ФП, конечно, подразумевает собой гораздо большее, но кое-какие полезные элементы почерпнуть из ФП, как видим, можно.
… Мои размышления привели к тому, что по-большому счету, работа современных программистов-разработчиков тоже бессмысленна. Она обладает «смыслом» в очень коротком временном промежутке. Это как сервис. Мы неустанно постоянно делаем одно и то же, и не замечаем это.
Где все те чудесные программы 80х и 90х? Где все прекрасные фреймворки? Библиотеки? (Читали «Design Patterns» — книжку из 90х? Обратили внимание, сколько прекрасных фреймворков там упомянуто? Десятки...) Где замечательные монбланы кода браузера Opera? Материки операционной системы OS/2? Тонны софта Amiga или Mac? Кто сейчас помнит о списке «3D engines list» со списком из 643 проектов? http://cg.cs.tu-berlin.de/~ki/engines.html Где кодовые базы десятков тысяч игр? А сколько движков сайтов или внутри-конторных базочек ушло на свалку истории? Представить страшно. А все еще только впереди — в последние 5-7 лет произошла сильная фрагментация. Сколько сейчас пишется кода на скриптовых, интерпретируемых и динамических JS, Go, Python, Ruby, PHP, Erlang… Десятки языков. Нет, я не пессимизирую, понятно что информационная сфера эфемерна и строго говоря, абстрактна. Но когда результаты человеческого труда живут 3-5 лет, а то и предназначены для развлечения, чтоб мелькнуть и забыть — что-то реально идет не так… Не задумывались об этом?
Что же касается «Про x и bar»
Не все так просто, как это написал автор. Это «хак» Weak symbol GCC и ELF, стандарт его (имхо) не оговаривает. С компилятором Visual C++ дело окончится ошибкой линкера «unresolved external symbol».
Здесь существует еще один скрытый фактор, осмысленный по-видимому не до конца. Google — очень большая компания с большим количеством подразделений и проектов. И на самом деле для успеха большое значение имеет над чем именно ты работаешь. Имеет значение команда, проект, подразделение.
Будучи «разменной монетой» и работая в «низах», на посредственных, бросовых проектах, которые в реальности не несут ключевую технологию компании, ты предсказуемо столкнешься с трудностями должностного роста. Сие есть закономерность, ее необходимо осмыслить и запомнить.
https://github.com/electronicarts/EASTL/blob/master/include/EASTL/allocator.h
Так там всё и есть. У OWL SafetyPool они в два раза больше взяли, 8К.
У Борландов сразу был предусмотрен callback с глобальной обработкой out of memory.
Ценю когда человек сразу url даёт. Сам такой. Поставил бы +1, но не могу.
я тоже не знаю одного универсального способа избавления от проверок в коде и тоже считаю что ситуация что и где использовать это гибкий вопрос.
p.s. коммент не просмотрите про буфер в паскале:
ссылка
Дайте ссылку хоть на какой-нибудь код, который принадлежит вашей руке.
Можно в ЛС.
Вот например khim дал в личной ссылке, насладиться я пока не успел, но все же почему он так много говорит о некоторых вещах понятно :)
1. Chromium меня не интересует. Если я его и упомянул, то только чтобы сказать что он «набор процессов», какой в нем malloc мне в текущем контексте вообще без разницы.
Поэтому смысла мне писать об этом ноль. В моей основной теме Chromium никак не звучал.
2. Про механизм malloc hooks в GLBC я в курсе, как и POSIX dlsym.
3. Теперь насчет «обертки», как это я понимал, когда произносил вам определенные слова выше и связывал их с memory manager.
Я тоже не знаю одного универсального способа избавления от проверок в коде и тоже считаю что ситуация что и где использовать это гибкий вопрос.
Вот например знакомый вам язык C++, кроме старых версий MSVC библиотек (хотя это фиксится), архитектурно решает вопрос контролем не проверками по месту в коде, а глобальной проверкой выполненной в operator new и выкидывающей std::bad_alloc.
То есть, он реализует глобальную парадигму проверки аллокации памяти (а не по месту).
Также, как звучавшее предложение.
Смеялся!
Извините, не распарсил все эти пространные рассуждения с увлечением какой есть паскаль и где его (вдруг!) можно взять.
Мдас. Как-то смешно у вас вышло.
Так я не понял, вы младше? Или старше?
Если младше, то видимо просто работа была не так давно? В каком году? BP/TP в 95ом заменила Delphi, я кстати на ней и писал.
У меня под боком в 2000 г. в банковской системе сидел товарищ на Clipper'е, ну так вы понимаете как мы его дразнили. Плывет по реке Клипер, на Клипере Шкипер, у Шкипера… :-)