一般来说,函数式语言中的模式匹配比Prolog中的模式匹配快或快。与Prolog相比,我希望Erlang能以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].
跑步者的一个更有趣的例子。在这里,我们可以在模式中利用跳过。如果(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]).
您必须自己运行此示例,并评估您是否认为它足够快才能满足您的用例。请注意,映射代码也花了一些时间,并且需要花费很多时间以将数据从主存储器通过CPU高速缓存拉到CPU。
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]).
当然,这个例子比较慢,因为我们需要在命中之前匹配更多的数据。但是这是一个更有趣的例子,因为它给出了匹配编译器实际速度的一些指示。
并行版本进行了尝试,但都是因为创造200万个工作进程的开销,在这种情况下慢10倍左右远占主导地位的实际处理:)
张贴科茨。改写为一个关于为什么会崩溃的问题。 – EvilTeach 2011-01-22 12:57:56
该代码是2个非常简单的程序。第一个程序是序列子句(0) - > 0的10个子句元首;条款(1) - > 0; (最多10个)为了测试我使用重复创建了200万个0的列表,并且使用map来映射子句到它上面。第二个程序是简单地使用重复创建200万列表中的7个整数,然后使用映射将sum映射到它。我再次试图测试用作编程技术的模式匹配的相对性能。我的问题是,是否鼓励Erlang程序员在Prolog程序员中使用模式匹配(如果可行)。 – Ultranewb 2011-01-22 16:50:39