LINUX.ORG.RU

ФВП и производительность

 , , ,


2

7

Провёл тест на скорость работы одной и той же функции, написанной нормально и через ФВП. Получил потерю производительности в полтора раза:

SBCL:

(declaim (optimize (speed 3) (safety 0)))

(asdf:oos 'asdf:load-op :alexandria)

(defun f (x)
  (+ (+ (+ x 1) 2) 1))

(let ((f-comp
          (alexandria:compose
            (lambda (x) (+ x 1))
            (lambda (x) (+ x 2))
            (lambda (x) (+ x 1)))))
  (defun f-comp (x)
     (funcall f-comp x)))

(defconstant iter 10000000)

(time
 (dotimes (i iter)
   (f i)))

(time
 (dotimes (i iter)
   (f-comp i)))


Evaluation took:
  0.181 seconds of real time
  0.180000 seconds of total run time (0.180000 user, 0.000000 system)
  99.45% CPU
  325,363,554 processor cycles
  0 bytes consed

Evaluation took:
  0.296 seconds of real time
  0.296000 seconds of total run time (0.296000 user, 0.000000 system)
  100.00% CPU
  530,610,480 processor cycles
  0 bytes consed

Racket:

#lang racket
(define (f x)
  (+ (+ (+ x 1) 2) 1))

(define f-comp
  (compose
   (lambda (x) (+ x 1))
   (lambda (x) (+ x 2))
   (lambda (x) (+ x 1))))

(define iter 1000000)

(time 
 (for ([i iter])
   (f i)))

(time 
 (for ([i iter])
   (f-comp i)))

cpu time: 728 real time: 726 gc time: 0
cpu time: 1244 real time: 1244 gc time: 0

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

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

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

anonymous
()
Ответ на: комментарий от cdshines

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

Simple Time: 61 
HOF Time: 332 
O HOF Time: 25 

Simple Time: 69 
HOF Time: 21 
O HOF Time: 4 

Simple Time: 4 
HOF Time: 20 
O HOF Time: 5 

Simple Time: 5 
HOF Time: 23 
O HOF Time: 5 

Simple Time: 5 
HOF Time: 25 
O HOF Time: 4 

Simple Time: 10 
HOF Time: 48 
O HOF Time: 4 

Simple Time: 4 
HOF Time: 25 
O HOF Time: 5 

Simple Time: 10 
HOF Time: 28 
O HOF Time: 6 

Simple Time: 4 
HOF Time: 25 
O HOF Time: 6 

Simple Time: 5 
HOF Time: 28 
O HOF Time: 6 

Simple Time: 18 
HOF Time: 44 
O HOF Time: 7 

Simple Time: 11 
HOF Time: 44 
O HOF Time: 5 

Simple Time: 6 
HOF Time: 25 
O HOF Time: 6 

Simple Time: 5 
HOF Time: 25 
O HOF Time: 9 

Simple Time: 14 
HOF Time: 26 
O HOF Time: 6 

Походу, оно там все заинлайнило, для оптимизированного HOF.

DiKeert ★★
()

Ответ на то почему ты о бенчмарке лиспа делаешь вывод о Haskell (и возможно других языках) в этом треде уже был?

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

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

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

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

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

Да я так, мимо проходил, я не слишком большой спец в фп, большого холливара не получится все равно.

Просто тс же написал

если там без них почти ничего написать нельзя

Вот от этого и пляшем.

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

anonymous
()
Ответ на: комментарий от privet

другую тоже но там нужный аргумент в середине и хрен ее закаррируешь

Языки/библиотеки (пример — ramda или lodash-func для жабоскрипта), рассчитанные на композицию, всегда имеют «нужный» аргумент последним и каррирование автоматом. Поэтому оно там и идиоматично.

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

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

anonymous
()
Ответ на: комментарий от x3al

всегда имеют «нужный» аргумент последним

Ок. Странно что на последнем. Я привык самый важный аргумент на первом месте видеть.

privet
()
Ответ на: комментарий от anonymous

Меньше эпитетов при обсуждении технических вещей желательно, т.к. они вообще не несут пооезной информации. Код с ФВП может быть гораздо более понятным и более абстрактным при той же и даже лучшей стабильности, т.е. ты смотришь на код и не играешь в интерпретатор, а понимаешь как он работает и что делает. Это не отменяет того, что можно написать ужасный функциональный код с применением ФВП, как с т.з. читабелтности так и производительности. Минус это то, что нужна специализация и поддержка кроссмодульного инлайна, при этом хорошо настраемого + хорошо механизм типа rewriting rules или более хороший. В Haskell оно есть, хотя бывают случаи, где специализировать лучше руками (не то чтобы я такие в работе всрэтречал более 1.5 раза).

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

К тому же громоздкий.

Вот это зря.

Подсчет расстояния между векторами на J с редьюсом и композицией:

    dist =: %:@:(+/)@:(*:@:-)
    1 2 1 dist  1 3 4
3.16228

anonymous
()
Ответ на: комментарий от privet

Если аргумент первый — нужны хаки вроде ->, который ставит аргумент, проходящий через цепочку, первым в функцию. Если он последний — можно просто каррировать каждую функцию в цепочке (обычно автоматически) и указывать только дополнительные аргументы. Тот же (.replace what to string) из примера выше с учётом каррирования в compose достаточно подставить (.replace_curried what to). Если будет (.replace string what to) (как он есть в clojure) — при честном функциональном compose придётся делать lambda(x) (replace x what to) и тут compose даром не нужен.

Поэтому и -> заточен под то, что в практически всех библиотеках обрабатываемый предмет — строка, массив, что там было, который будет пропускаться через compose/pipe — стоит первым.

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

Это сахар. Ты показал частный случай, в общем же случае будет отсос, потому что прежде чем что-то специализировать нужно все определять. Если ООП подход — это расширение + специализация, то ФП подход — это только специализация, в этом основное различие.

К тому же, этот перл-стайл программирование нахрен не нужно. Чем более закомплексованный язычок, тем больше в нем всяких сокращений &&^^%$$%###$%%^^. В нормальных языках, таких, например, как tcl, Io, подобное дерьмо вобще не принято. там все пишется полным текстом обычно. Пользователь сам решает, что ему сокращать, а что нет. А эти языки похожи на малоростка, который носит обувь на высокой платформе, чтобы казаться выше.

anonymous
()
Ответ на: комментарий от x3al

Да, перепутал. Обычно второстепенные нужно каррировать если много аргументов у функции. Попробую как-нибудь этот ваш `->' :)

privet
()
Ответ на: комментарий от anonymous

Любитель COBOL в треде, все в легаси.

anonymous
()
Ответ на: комментарий от x3al

ФП — можно считать частным случаем ООП. ООП реализует семантику ФП. Но не ноборот. Это с точки зрения семантики.

А с точки зрения чистоты, это имеет смысл только для ФП.


f=function(x){return y}
f(clean_long_function())// в энергичном языке все равно будет долго считать.

Если в ФП с нормальным порядком, или даже аппликативном, где компилятору гарантируется чистота, программист заключает договор с компилятором: я буду писать с большими ограничениями, громоздко, ради оптимизации, то в языке, где чистые функции никак не оптимизируются, ты просто занимаешься мазохизмом, когда пишешь в таком стиле.

anonymous
()
Ответ на: комментарий от x3al

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

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

ФП — можно считать частным случаем ООП. ООП реализует семантику ФП. Но не ноборот.

Пошёл бы и поучил матчасть, что ли.

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

ради оптимизации

Быстро ушёл с ЛОРа учить матчасть. Пока не перестанешь нести чушь — не возвращайся.

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

Одну функцию нужно закаррировать, другую тоже но там нужный аргумент в середине и хрен ее закаррируешь

Это как раз не проблема

((compose 
  first
  (cut string-split <> " ") 
  (cut string-replace <> "A" "X")
  string-upcase)
 "a b c d")
"X"

третья вообще макросом оказывается

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

На самом деле можно сделать compose, чтобы он при вызове (compose ...) был макросом, а при (f compose) — функцией. В CL для этого есть define-compiler-macro, а в Racket — syntax-id-rules. Хотя по хорошему этим должен заниматься компилятор (в g++ ведь как-то справляется).

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

Это не просто матчасть, это основы основ, которые ты ниасилил. Я надеюсь, пока.

То что ты называешь матчастью — это кукареканья фанбоев, с лора и других жежешечек. Такую матчасть я изучать не буду.

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

Это бред. Он наоборот неулюжий и нечитаемый. К тому же громоздкий. Единственный профит от этого кода — то что он хорошо оптимизируется.

Так про то и речь, что плохо оптимизируется. По крайней мере в лиспах.

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

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

anonymous
()
Ответ на: комментарий от monk

С точки зрения CS термин ФП имеет вполне четкое определение: подстановочная модель вычислений. Лисп не является ФП-языком, его так обзывают по недоразумению. Он не более функционален чем JS. В лиспе ООП имитируется конечно, засчет окружений и присваиваний. Этому целая глава в SICP посвящена.

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

Кормлю анонiмуса, впрочем, он всё равно не умеет читать

То что ты называешь матчастью — это кукареканья фанбоев, с лора и других жежешечек. Такую матчасть я изучать не буду.

why-fp-matters.pdf в этом случае и не забывай, что ты — фанбой с ЛОРа, не выучивший матчасть.

Though OOP came from many motivations, two were central. The large scale one was to find a better module scheme for complex systems involving hiding of details, and the small scale one was to find a more flexible version of assignment, and then to try to eliminate it altogether. As with most new ideas, it originally happened in isolated fits and starts.

Угадай, кого цитирую. Или ты будешь утверждать, что eliminate assigbnment altogether ≠ иммутабельности?

Никто не спорит, что современные языки зачастую мультипарадигменны, но это не значит, что ООП включает в себя ФП: они ортогональны. ООП про инкапсуляцию, полиморфизм и абстракцию, ничто из этого не исключает иммутабельность. Но из того, что мультипарадигменный язык может и в ООП, и в ФП, ничерта не следует, что этот язык нужно зачислять в ООП: примеры — scala, f#.

Ну и вообще, http://stackoverflow.com/a/2079678/2815355

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

Лисп не является ФП-языком, его так обзывают по недоразумению. Он не более функционален чем JS. В лиспе ООП имитируется конечно, засчет окружений и присваиваний.

http://www.rubendegooijer.nl/posts/2013-04-06-haskell-oop.html

monk ★★★★★
() автор топика

Угадай, кого цитирую. Или ты будешь утверждать, что eliminate assigbnment altogether ≠ иммутабельности?

подозреваю, что ты вообще не понял смысла это фразы. С точки зрения ООП никакого присваивания вообще нет, есть только сообщения. Это никакого отношения к состоянию не имеет.

Ну и вообще

ну я же говорил, что ты будешь кидать пруфы уровня жежешечек.

Functional languages are good when you have a fixed set of things, and as your code evolves, you primarily add new operations on existing things. This can be accomplished by adding new functions which compute with existing data types, and the existing functions are left alone.

То есть, по мнению Васи, расширять классы новыми методами и приментяь сторонние функции к объектам в ООП запрещается. Ок.

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

С точки зрения ООП никакого присваивания вообще нет, есть только сообщения

Для начала нам нужно определиться с терминологией. Твоя конкретно тут, пусть и популярна, просто ошибочна даже по мнению Алана Кея. Впрочем, ты ничерта в ней не разбираешься всё равно.

То есть, по мнению Васи, расширять классы новыми методами и приментяь сторонние функции к объектам в ООП запрещается. Ок.

То есть расширять классы новыми методами может быть ДОРОГО в человекочасах.

Никто не спорит, что это теоретически возможно.

ну я же говорил, что ты будешь кидать пруфы уровня жежешечек.

Просто ты пропустил то, что я тебе кинул первым. Сенсация, анонiмус — тролль и демагог.

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

Я еще раз повторяю. С точки зрения CS ФП — это подстановочная модель вычислений. То что там Вася Пупкин понимает под ФП меня не интересует. Кто бы сомневался, что в хаскеле куча костылей, на которых что-то можно имитировать. Но речь идет о парадигме как таковой.

anonymous
()
Ответ на: комментарий от x4DA

Я понимаю, почему это спрашивает анонимус, но зачем это тебе? За пределами closures are poor man's objects and vice versa ООП и ФП-подходы достаточно разные.

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

С точки зрения CS ФП — это подстановочная модель вычислений.

[citation needed], поскольку это на данный момент с точки зрения анонiмуса, а не CS. Ты об этом год назад писал, тебе советовали выдохнуть. Или твои труды теперь фундаментальны в CS?

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

то, что я тебе кинул первым

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

может быть ДОРОГО в человекочасах.

Ага, а может быть и дешево. Заявляние в стиле «ни о чем».

anonymous
()
Ответ на: комментарий от x3al

Ты об этом год назад писал, тебе советовали выдохнуть. Или твои труды теперь фундаментальны в CS?

Еще раз повторяю, это общепринятая точка зрения в CS. Для ознакомления можешь почитать SICP

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

К ФП вообще ничего не имеет никакого отношения, пока мы его не определим. И твоё определение — говно.

По моему определению, ФП-язык == язык, позволяющий функции высшего порядка. Следовательно, любой язык с замыканиями == ФП. Это определение как минимум имеет смысл на практике. А дальше можно делить на pure и прочее.

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

Еще раз повторяю, это общепринятая точка зрения в CS. Для ознакомления можешь почитать SICP

Ох лол.

Не все функциональные ЯП и не обязательно целиком обладают ссылочной прозрачностью. «Функциональность» — не бинарное понятие, а скорее градация. Чёткого определения «функциональности» ЯП в CS сейчас нет вообще.

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

По моему определению, ФП-язык == язык, позволяющий функции высшего порядка. Следовательно, любой язык с замыканиями == ФП.

Ну дык, у тебя вообще каша в голове. В огороде бузина, а следовательно в киеве дядя. Замыкани к ФВП тоже не имеют никакого отношения. Причем, независимо от практики.

anonymous
()
Ответ на: комментарий от x3al

ссылочной прозрачностью

Да и ссылочная прозрачность к ФП имеет весьма косвенное отношение, кстати.

anonymous
()
Ответ на: комментарий от x3al

У тебя мозг наизнанку вывернут. Никто не заставляет *делать замыкания*. Речь о том, что ФВП прекрасно обходятся без замыканий.

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

Следовательно, любой язык с замыканиями == ФП.

Речь о том, что ФВП прекрасно обходятся без замыканий.

Логика. Анонимус, ты в неё умеешь?

Если есть замыкания, то есть ФВП. Это не значит, что если есть ФВП, то есть замыкания.

Да и ссылочная прозрачность к ФП имеет весьма косвенное отношение, кстати.

Эмм. Ты же уже хз сколько времени твердишь о подстановочной модели вычислений.

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

Логика.

LOL? Ты реально в 2-х соснах запутался. В лиспах, в которых нет лексического связывания, есть ФВП, внезапно, например:).

anonymous
()
Ответ на: комментарий от x3al

Ты же уже хз сколько времени твердишь о подстановочной модели вычислений.

Я тебе недавно приводил ссылку на бумагу Карла Хьюитта, где он говорит, что в модели Акторов, реализована ссылочная прозрачность.

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