0

При написании функции, как факториал:инструменты производительности для Эрл

fac(Val) when is_integer(Val)-> 
    Visit = fun (X, _F) when X < 2 -> 
        1; 
       (X, F) -> 
        X * F(X -1, F) 
      end, 
    Visit(Val, Visit). 

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

fac_cps(Val) when is_integer(Val)-> 
    Visit = fun (X, _F, K) when X < 2 -> 
        K (1); 
       (X, F, K) -> 
        F(X-1, F, fun (Y) -> K(X * Y) end) 
      end, 
    Visit(Val, Visit, fun (X) -> X end). 

Или, возможно, даже defunctionalized:

fac_cps_def_lambdas({lam0}, X) -> 
    X; 
fac_cps_def_lambdas({lam1, X, K}, Y) -> 
    fac_cps_def_lambdas(K, X*Y). 


fac_cps_def(X) when is_integer(X) -> 
    fac_cps_def(X, {lam0}). 

fac_cps_def(X, K) when X < 2 -> 
    fac_cps_def_lambdas(K,1); 
fac_cps_def(X, K) -> 
    fac_cps_def(X-1, {lam1, X, K}). 

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

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

Что такое стандартные инструменты для проверки таких вещей?

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

ответ

3

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

Это просто интуиция для меня. Вы можете проверить размер стека процесса с помощью erlang:process_info/2. Вы может проверить время выполнения с fprof. Но я делаю это только как последнее исправление.

+0

Одна из вещей, которые мне интересны в том, чтобы выяснить, насколько работает LCO erlang, без меня спрашивает, и когда имеет смысл делать это самостоятельно, и я просто хотел это проверить.Я знаю, что последняя версия будет оптимизирована, но как насчет первой, будет ли «X * F (X -1, F)» означать, что мы получаем стек из X, который затем умножается вместе, хотя стек? –

+1

Нет. Оливье, вероятно, написало бы '(* X (F (-1 X) F))' или что-то подобное в Схеме, и тогда довольно ясно, что последнее, что делает предложение функции, - это умножение, а не вызов функции. Следовательно, TCO/LCO не может применяться и не оптимизируется. * Другое * вещь, на которую нужно обратить внимание, - это попытка ... catch, которая толкает обработчик в стек, который раскручивает его, даже если ваш вызов находится в хвостовой позиции. –

+0

он бы, и, насколько я помню, он не самый большой поклонник мира Эрланг ... –

2

Это не отвечает на ваш вопрос, но почему вы написали такой код? Это не очень Эрланги. Обычно вы не используете явный CPS, если для этого нет конкретной причины, обычно это не требуется.

Как @IGIVECRAPANSWERS говорит, что вы скоро научитесь видеть хвост-звонки, и Есть очень мало случаев, когда вы на самом деле ДОЛЖЕН использовать его.

EDIT: Комментарий к комментарию. Нет никакого прямого способа проверить, использовал ли компилятор LCO или нет. Он делает именно то, что вы рассказываете, и предполагает, что вы знаете, что делаете, и почему. :-) Тем не менее, вы можете быть уверены, что это происходит, когда это возможно, но что это так. Единственный способ проверить - посмотреть размер стека процесса, чтобы увидеть, растет ли он или нет. К сожалению, если вы ошибаетесь в правильном месте, процесс может расти очень медленно, и его трудно обнаружить, за исключением длительного периода времени.

Но снова очень мало мест, где вам действительно нужно получить LCO.

P.S. Вы используете термин LCO (Last Call Optimization), который я узнал раньше. Теперь, однако, «они», похоже, используют TCO (Tail Call Optimization). Это прогресс. :-)

+0

Справа мой код не очень erlangy, я начал свои функциональные дни программирования, делая sML. Однако вопрос остается тем же. В основном, есть способ проверить погоду? –

+0

Кстати, я узнал термин «Оптимизация последнего звонка» у профессора Оливье Данви, самого цитируемого человека в науке, и я не собираюсь менять его на какое-то растение. :-) –

Смежные вопросы