这是一个简单的程序,我的机器有两个CPU核心。 我希望当我生成两个进程时,消耗时间与我只生成一个进程的时间相同。
-module(test).
-export([main/1]).
forRange(Begin,End,Total) when Begin < End ->
forRange(Begin+1,End,Total+Begin);
forRange(_,_,Total)->
io:format("~p ~n", [Total]),
ok.
main([A, B])->
process_flag(trap_exit, true),
Pids = [spawn_link(fun() -> forRange(1,list_to_integer(A),0) end) || _ <- lists:seq(1, list_to_integer(B))],
[ receive
{'EXIT', Pid, normal} ->
ok
end || Pid <- Pids ].
测试结果是:
$ time escript test.beam 1000000000 1
499999999500000000
real 0m3.895s
user 0m3.820s
sys 0m0.068s
$ time escript test.beam 1000000000 2
499999999500000000
499999999500000000
real 0m4.582s
user 0m8.788s
sys 0m0.168s
但是,结果表明,当我生成两个进程时,实际时间比一个进程的情况要大,这意味着Erlang调度程序有一些开销?但是对于这个简单的例子,这些过程应该完全并行运行。
答案 0 :(得分:3)
我已经为编译模块修改了一点代码。
-module(test).
-export([test/2]).
forRange(Begin,End,Total) when Begin < End ->
forRange(Begin+1,End,Total+Begin);
forRange(_,_,Total)->
io:format("~p ~n", [Total]),
ok.
test(A, B)->
Flag = process_flag(trap_exit, true),
Pids = [spawn_link(fun() -> forRange(1,A,0) end) || _ <- lists:seq(1, B)],
[ receive
{'EXIT', Pid, normal} ->
ok
end || Pid <- Pids ],
process_flag(trap_exit, Flag).
然后我编译并运行。
$ erlc test.erl
$ erl -tbt
Erlang/OTP 18 [erts-7.0] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V7.0 (abort with ^G)
1> timer:tc(fun() -> test:test(500000000,1) end).
124999999750000000
{8218153,true}
2> timer:tc(fun() -> test:test(500000000,1) end).
124999999750000000
{8292624,true}
3> timer:tc(fun() -> test:test(500000000,2) end).
124999999750000000
124999999750000000
{9119394,true}
4> timer:tc(fun() -> test:test(500000000,2) end).
124999999750000000
124999999750000000
{9116651,true}
5> (9116651+9119394)/(8218153+8292624).
1.10449344691652
正如你所看到的,我故意做了两件事。首先,我将调度程序锁定到CPU内核,然后我选择重复次数来运行它更长,几乎是10s。目的是使其更具可预测性,为调度员提供更多时间来安排工作,并使测量更加稳定。正如你所看到的,差异现在只有10%。我有现代CPU(型号名称:Intel(R)Core(TM)i5 CPU M 520 @ 2.40GHz),如果只使用一个CPU核心,我可以自动超频,我倾向于将这种差异归咎于此。
如果您希望查看调度程序开销,则应尝试更多进程:
1> timer:tc(fun() -> test:test(100000000,16) end).
4999999950000000
...
4999999950000000
{13466677,true}
2> timer:tc(fun() -> test:test(100000000,16) end).
...
{13625811,true}
3> timer:tc(fun() -> test:test(100000000,32) end).
...
{27325526,true}
4> timer:tc(fun() -> test:test(100000000,32) end).
...
{27461209,true}
5> (27325526+27461209)/(13466677+13625811)/2.
1.0111056430107122
现在这1.1%你可能可以归咎于schdeulers开销。
答案 1 :(得分:0)
在&#39; 2&#39;例如,您创建的流程数量是原来的两倍 由于进行产卵的过程是单线程的,因此需要更长的时间来产生两倍的产卵。 一个更好的方式来展示我认为你想要展示的内容将是产生B流程,每个流程都会产生一个流程。这样,实际的产卵也是并行完成的。