Как правило, сопоставление с образцом в функциональных языках происходит быстрее или быстрее, чем в Прологе.Я ожидаю, что Эрланг будет работать с коэффициентом 2 по сравнению с Прологом быстрее или медленнее.Поскольку функциональная программа - это не что иное, как сопоставление с образцом, это одна из тех областей, которые вы оптимизируете.
Внутренние компоненты обычно имеют компилятор сопоставления с образцом , который превращает расширенное сопоставление с образцом в более простоесерия проверок с целью минимизации количества проверок.
Хорошо, первая ошибка: " Все, что введено в оболочку, интерпретируется ".Поэтому вместо этого мы компилируем модули:
-module(z).
-compile(export_all).
%% This pattern is highly uninteresting because it only matches
%% on a single value. Any decent system can do this quickly.
cl(0) -> 0;
cl(1) -> 0;
cl(2) -> 0;
cl(3) -> 0;
cl(4) -> 0;
cl(5) -> 0;
cl(6) -> 0;
cl(7) -> 0;
cl(8) -> 0;
cl(9) -> 0.
mcl(L) ->
[cl(E) || E <- L].
Это дает нам бегун вашего примера.
cl2(a, 0) -> a0;
cl2(a, 1) -> a1;
cl2(a, 2) -> a2;
cl2(b, 0) -> b0;
cl2(b, 1) -> b1;
cl2(b, 2) -> b2;
cl2(c, 0) -> c0;
cl2(c, 1) -> c0;
cl2(c, 2) -> c0.
mcl2(L) ->
[cl2(A, V) || {A, V} <- L].
Бегун для более интересного примера.Здесь мы можем использовать skips в паттерне.Если (a, 0)
не совпадает с a
, мы знаем, что можем сразу перейти к случаю (b, 0)
, поскольку информация об отрицательном совпадении может распространяться как информация в системе.Компилятор сопоставления с образцом обычно выполняет эту оптимизацию.
test1() ->
L1 = [X rem 10 || X <- lists:seq(1, 2000000)],
%% A Core 2 Duo 2.4Ghz P8600 eats this in 132984 microseconds without HiPE
%% c(z).
%% With HiPE it is 91195 or in 0.6857591890753775 of the time the non-HiPE variant use
%% c(z, [native, {hipe, [o3]}]).
timer:tc(z, mcl, [L1]).
Вы должны запустить этот пример самостоятельно и оценить, считаете ли вы, что он достаточно быстр для вашего варианта использования.Обратите внимание, что некоторое время также затрачивается на код отображения и довольно много времени должно быть потрачено на извлечение данных из основной памяти через кэш-память ЦП в ЦП.
test2() ->
random:seed(erlang:now()),
L2 = [{case random:uniform(3) of
1 -> a;
2 -> b;
3 -> c
end, V rem 3} || V <- lists:seq(1, 2000000)],
%% With HiPE this is 220937
%% Without HiPE this is 296980
timer:tc(z, mcl2, [L2]).
Естественно, этот пример медленнее, так как нам нужно сопоставить больше данных, прежде чем мы получим попадание.Но это более интересный случай, потому что он дает некоторое представление о реальной скорости компилятора соответствия.
Были испробованы параллельные версии, но в этом случае они примерно в 10 раз медленнее, так как накладные расходы на создание 2 миллионов рабочих процессов намного преобладают над фактической обработкой:)