代码:
1 -module(lib_misc).
2 -export([pmap/2]).
3 -import(lists, [foreach/2]).
4
5 pmap(F, L) ->
6 S = self(),
7 %%Ref = erlang:make_ref(),
8 lists:foreach(fun(I)->
9 spawn(fun() ->do_f(S, F, I) end)
10 end, L),
11 gether(length(L), []).
12
13 do_f(P, F, I) ->
14 P ! {self(), catch F(I)}.
15
16 gether(0, L) -> L;
17 gether(Len, L) ->
18 receive
19 {_Pid, I} -> gether(Len-1, [I|L])
20 end.
1 -module(ptests).
2 -export([tests/1, fib/1, simple/1]).
3 -import(lists, [map/2]).
4 -import(lib_misc, [pmap/2]).
5
6 tests([N]) ->
7 Nsched = list_to_integer(atom_to_list(N)),
8 run_tests(1, Nsched).
9
10 run_tests(N, Nsched) ->
11 case test(N) of
12 stop ->
13 init:stop();
14 Val ->
15 io:format("~p,~n", [{Nsched, Val}]),
16 run_tests(N+1, Nsched)
17 end.
18
19 test(1) ->
20 seed(),
21 S = lists:seq(1, 100),
22 L = map(fun(_) -> mkList(1000) end, S),
23 {Time1, S1} = timer:tc(lists, map, [fun lists:sort/1, L]),
24 {Time2, S2} = timer:tc(lib_misc, pmap, [fun lists:sort/1, L]),
25 {sort, Time1, Time2, equals(S1, S2)};
26 test(2) ->
27 L = lists:duplicate(100, 27),
28 {Time1, S1} = timer:tc(lists, map, [fun ptests:fib/1, L]),
29 {Time2, S2} = timer:tc(lib_misc, pmap, [fun ptests:fib/1, L]),
30 {fib, Time1, Time2, equals(S1, S2)};
31 test(3) ->
32 L = lists:duplicate(100, 27),
33 {Time1, S1} = timer:tc(lists, map, [fun ptests:simple/1, L]),
34 {Time2, S2} = timer:tc(lib_misc, pmap, [fun ptests:simple/1, L]),
35 {simp, Time1, Time2, equals(S1, S2)};
36 test(4) ->
37 stop.
38
39 equals(S, S) -> true;
40 equals(S1, S2) when S1 /= S2-> different.
41
42 fib(0) -> 0;
43 fib(1) -> 1;
44 fib(N) -> fib(N-1) + fib(N-2).
45
46 simple(N) -> N*2.
47
48 seed() -> random:seed(44, 55, 66).
49
50 mkList(K) -> mkList(K, []).
51 mkList(0, L) -> L;
52 mkList(N, L) -> mkList(N-1, [random:uniform(1000000) | L]).
执行脚本:
1 #! /bin/sh
2 echo "">results
3 for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
4 do
5 echo $i
6 erl -noshell -smp +S $i -s ptests tests $i >> results
7 done
其中的一次执行结果:(经过我整理,便以查看,如下:)
1 {1, {sort,46801,53680,different}},
2 {2, {sort,46816,34387,different}},
3 {3, {sort,47577,22461,different}},
4 {4, {sort,49070,24194,different}},
5 {5, {sort,46981,21199,different}},
6 {6, {sort,48144,21853,different}},
7 {7, {sort,51281,21976,different}},
8 {8, {sort,47351,16202,different}},
9 {9, {sort,49418,18515,different}},
10 {10,{sort,47851,18385,different}},
11 {11,{sort,47211,17063,different}},
12 {12,{sort,51277,16826,different}},
13 {13,{sort,48071,17808,different}},
14 {14,{sort,47557,19034,different}},
15 {15,{sort,47976,16434,different}},
16 {16,{sort,47507,18308,different}},
17 {17,{sort,47713,18712,different}},
18 {18,{sort,46753,18683,different}},
19 {19,{sort,47454,16730,different}},
20 {20,{sort,47541,18095,different}},
21 {21,{sort,46717,18154,different}},
22 {22,{sort,47381,18109,different}},
23 {23,{sort,47441,17849,different}},
24 {24,{sort,47130,16926,different}},
25
26 {1, {fib,2249210,2239440,true}},
27 {2, {fib,2237625,1142294,true}},
28 {3, {fib,2314723,776341,true}},
29 {4, {fib,2219352,589694,true}},
30 {5, {fib,2223962,458944,true}},
31 {6, {fib,2205473,383569,true}},
32 {7, {fib,2228012,329824,true}},
33 {8, {fib,2201455,289698,true}},
34 {9, {fib,2222083,295472,true}},
35 {10,{fib,2196697,289709,true}},
36 {11,{fib,2221117,292360,true}},
37 {12,{fib,2201498,288787,true}},
38 {13,{fib,2447176,289420,true}},
39 {14,{fib,2230599,288047,true}},
40 {15,{fib,2221310,290624,true}},
41 {16,{fib,2200155,288700,true}},
42 {17,{fib,2196464,288331,true}},
43 {18,{fib,2231116,288998,true}},
44 {19,{fib,2223387,287379,true}},
45 {20,{fib,2223563,289634,true}},
46 {21,{fib,2208410,288783,true}},
47 {22,{fib,2230869,288493,true}},
48 {23,{fib,2593730,335768,true}},
49 {24,{fib,2229330,290668,true}},
50
51 {1, {simp,10,313,true}},
52 {2, {simp,15,724,true}},
53 {3, {simp,13,819,true}},
54 {4, {simp,19,857,true}},
55 {5, {simp,19,827,true}},
56 {6, {simp,17,813,true}},
57 {7, {simp,19,860,true}},
58 {8, {simp,15,916,true}},
59 {9, {simp,17,822,true}},
60 {10,{simp,19,870,true}},
61 {11,{simp,16,816,true}},
62 {12,{simp,18,775,true}},
63 {13,{simp,19,864,true}},
64 {14,{simp,19,825,true}},
65 {15,{simp,17,859,true}},
66 {16,{simp,18,868,true}},
67 {17,{simp,15,846,true}},
68 {18,{simp,19,805,true}},
69 {19,{simp,19,843,true}},
70 {20,{simp,14,795,true}},
71 {21,{simp,17,775,true}},
72 {22,{simp,21,843,true}},
73 {23,{simp,17,837,true}},
74 {24,{simp,18,772,true}},
执行环境:
CentOS release 5.5 (Final),4核,8超线程,8G内存
结论:
map是单进程的,开多少SMP根本对它没什么影响,这是毋庸置疑的;
pmap是多进程的,开多少SMP根据不同的情况是有不同影响的,sort是小计算,随着SMP的增大性能提高相对于fib并不大,而fib是大计算,随着SMP的增大性能提高有明显幅度;
另外SMP要开多少个,基本是和逻辑CPU个数一样,基本上能保持稳定的最佳性能;最后对于simple这么简单的计算,采用什么SMP和进程策略都是弄巧成拙的,-smp disable和单进程就行了。
总之,单进程or多进程?SMP开多少?都是根据不同情况判断的。
最后将会测试pmap如果要处理很大的列表,开多少个进程合适?