2011-01-22 45 views
6

Erlang新款。我即将开始编写一些代码。我想到的解决方案可以通过两种方式之一。我可以做一堆数学计算,或者我可以将它编码为模式匹配。当我说“模式匹配”时,我并不是指正则表达式或类似的东西 - 我指的是从句头中的模式匹配。Erlang图案匹配性能

表现通常不是一个问题,但在这个应用程序是。我不是问你哪种方法会更快 - 我相信你会说你不知道(取决于很多因素)。我所要求的是在子句头中的Erlang模式匹配的一般性能。换句话说,在Prolog中,引擎被优化来完成这样的事情,所有其他的事情都是平等的,所以“鼓励”你设计一个解决方案,利用模式匹配和子句头的统一。

Erlang是否也是如此,即Erlang是否为子句头中的模式匹配进行了优化,类似于Prolog?我并没有在这里提出这个问题,而是试着在Erlang中描述这个问题,并且编写了一个玩具程序,对几百万次的子句头进行模式匹配,并对几百万次的列表进行总结。但是如果这个系统能够“几百万次”的话,系统就会崩溃。但设定为不到几百万美元,结果会回来太快,让我无法了解任何有关性能的信息。

感谢您的任何见解。

+3

张贴科茨。改写为一个关于为什么会崩溃的问题。 – EvilTeach 2011-01-22 12:57:56

+0

该代码是2个非常简单的程序。第一个程序是序列子句(0) - > 0的10个子句元首;条款(1) - > 0; (最多10个)为了测试我使用重复创建了200万个0的列表,并且使用map来映射子句到它上面。第二个程序是简单地使用重复创建200万列表中的7个整数,然后使用映射将sum映射到它。我再次试图测试用作编程技术的模式匹配的相对性能。我的问题是,是否鼓励Erlang程序员在Prolog程序员中使用模式匹配(如果可行)。 – Ultranewb 2011-01-22 16:50:39

回答

6

一般来说,函数式语言中的模式匹配比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倍左右远占主导地位的实际处理:)

5

它基本上是为@(不是很)CRAP答案:-)已经说过,他的例子显示。

序言没有真正做模式匹配,这是单向的,它确实是统一这就像是一个双向模式与逻辑变量匹配。优化模式匹配要容易得多,Erlang和Haskell等严重的函数式语言将相当多的工作放到优化模式匹配编译器中。深度图案尤其引人注目。

所以,是的,Erlang会比Prolog更快地进行模式匹配。