一般來說,函數式語言中的模式匹配比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