-module(exe5_2).
-export([start/2]).
%Points 是投掷点的个数 Cores是核数,为2的幂
start(Points,Cores)
->spawn(fun()->parent_proces(Points,Cores) end),
io:format("").
parent_proces(Points,Cores) ->
PointsPerProcess = Points div Cores,
creat_child_proces(Points,PointsPerProcess,Cores,Cores,[]).
%创建子进程
creat_child_proces(Points,PointsPerProcess,Cores,N,L)
when N =:=1 ->
Pid = spawn(fun()->process_points(Points,Points-PointsPerProcess*(Cores-1)) end),
Father = self(),
PidR = spawn(fun()->loop_control(Father,0,Cores,2) end),
sendInfo(L++[Pid]++[PidR],1,Cores,2,Cores);
creat_child_proces(Points,PointsPerProcess,Cores,N,L)
->Pid=spawn(fun()->process_points(Points,PointsPerProcess) end),
creat_child_proces(Points,PointsPerProcess,Cores,N-1,L++[Pid]).
%计算命中的点
process_points(Points,PointsPerProcess) ->
apply(random, seed, tuple_to_list(now())),
Count = test_points(PointsPerProcess, 0),
io:format("~p ‘s result is ~p~n",[self(),Count]),
loop_send_get(Points,Count).
test_points(0, Count) -> Count;
test_points(PointsPerProcess, Count) ->
X = (random:uniform() * 2) - 1,
Y = (random:uniform() * 2) - 1,
I = X*X + Y*Y,
if
I < 1 ->
test_points(PointsPerProcess - 1, Count + 1);
true ->
test_points(PointsPerProcess - 1, Count)
end.
%子进程部分和的发送和接收,由主进程sendInfo方法控制
loop_send_get(Points,Sum) ->
receive
{From,Sum1,Father,PidR} ->
io:format("~p from ~p to ~p result is ~p ~n",[Sum1,From,self(),Sum1+Sum]),
PidR!{"ok"},
loop_send_get(Points,Sum+Sum1);
{Pid,Father,PidR} ->
Pid!{self(),Sum,Father,PidR};
{"getRes"} ->Res=(Sum/Points)*4,
io:format("Pi:~p~n",[Res])
end.
%控制每一轮迭代求和的次数,N为一轮迭代中求和的次数,初始值为0,Divisor为控制变量,初始值为2
loop_control(Father,N,Cores,Divisor) ->%io:format("N:~p Divisor:~p~n",[N,Divisor]),
if
Cores =:= N*Divisor ->
Father!{self(),"over"},
loop_control(Father,0,Cores,Divisor*2);
true ->
receive
{"ok"} -> loop_control(Father,N+1,Cores,Divisor)
end
end.
sendInfo(PidList,N,Cores,Divisor,Dsum) ->%io:format("Pidlist:~p ~nN:~p Cores:~p Divisor:~p Dsum:~p ~n",[PidList,N,Cores,Divisor,Dsum]),
Nt = erlang:trunc(N),
if
Divisor =:= 2*Dsum -> Pid_1=lists:nth(1,PidList),
Sum=Pid_1!{"getRes"};
Nt > Cores ->
receive
{From,"over"} ->sendInfo(PidList,1,Cores-Divisor/2,Divisor*2,Dsum)
end;
Nt rem Divisor =:= 1 ->
sendInfo(PidList,N+Divisor/2,Cores,Divisor,Dsum);
Nt rem Divisor =/= 1 ->
Pid_send = lists:nth(Nt,PidList),
Pid_get = lists:nth(erlang:trunc(Nt-Divisor/2),PidList),%io:format("send:~p get:~p~n",[Pid_send,Pid_get]),
Pid_send!{Pid_get,self(),lists:nth(erlang:trunc(Dsum+1),PidList)},
sendInfo(PidList,N+Divisor/2,Cores,Divisor,Dsum)
end.
原文地址:http://blog.csdn.net/li8630/article/details/45150543