performance - Erlang 模式匹配性能

标签 performance erlang pattern-matching

Erlang 的新手。我即将开始编写一些代码。我想到的解决方案可以采用两种方式之一。我可以做一堆数学计算,或者我可以将其编码为模式匹配。当我说“模式匹配”时,我不是指正则表达式或类似的东西——我指的是子句头中的模式匹配。

性能通常不是问题,但在这个应用程序中它是。我不是在问你哪种方法会更快——我敢肯定你会说你不知道(取决于许多因素)。我要问的是 Erlang 模式匹配在子句头中的一般性能。换句话说,在 Prolog 中,引擎被优化来做这种事情,所以在所有其他条件相同的情况下,你被“鼓励”设计一个利用模式匹配和子句统一的解决方案。

Erlang 是否也是如此,即 Erlang 是否针对子句头部中的模式匹配进行了优化,类似于 Prolog?我实际上并没有在这里问这个问题,而是尝试在 Erlang 中对此进行分析,并编写了一个玩具程序来进行几百万次子句头部的模式匹配,而不是对一个列表求和几百万次。但是如果设置为“几百万次”,系统就会崩溃。但是如果设置为少于几百万,结果会返回得太快,以至于我对性能一无所知。

感谢您的任何见解。

最佳答案

一般来说,函数式语言中的模式匹配与 Prolog 中的一样快或更快。与 Prolog 相比,我希望 Erlang 的性能在 2 倍以内,更快或更慢。由于功能程序几乎只是模式匹配,因此它是您需要优化的领域之一。

内部通常有一个模式匹配编译器,它将高级模式匹配转换为更简单的一系列检查,目标是最大限度地减少检查次数。

好的,第一个问题:“shell 中引入的任何内容都被解释了”。所以我们编译模块:

-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]).

这个例子自然会比较慢,因为我们需要匹配更多的数据才能命中。但这是一个更有趣的案例,因为它给出了匹配编译器真实速度的一些指示。

尝试了并行版本,但在这种情况下它们慢了大约 10 倍,因为创建 200 万个工作进程的开销远远支配了实际处理:)

关于performance - Erlang 模式匹配性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4767908/

相关文章:

r - 从R中的字符串中提取特定关键字

pattern-matching - 在模式匹配期间防止 move 语义

javascript - 根据第一个真实条件评估表达式

java - 在主线程中创建字体会影响应用程序性能吗?

ruby - 从 Ruby 调用 Erlang

python - Django项目很慢

callback - 适合初学者的 Erlang/OTP 行为

erlang - 为什么我的 iex session 的 pid 总是相同?

c++ - 区分两个零参数构造函数的惯用方法

c - 如何快速读取和解析带有数字的文本文件(在 C 中)?