这个代码写了两天,从没思路到有思路,还好最终搞定了~不过这个进程数必须为2^n个。
先贴一个运行截图:
-module(exe4).
-export([start/5]).
start(F,X1,X2,Num,Cores)
->spawn(fun()->parent_proces(F,X1,X2,Num,Cores) end),
io:format("").
parent_proces(F,X1,X2,Num,Cores)
->creat_child_proces(F,X1,X2,(X2-X1)/Num,erlang:trunc(Num/Cores),Cores,Num,Cores,[]).
creat_child_proces(F,X1,X2,Width,Num_Per_Core,Cores,Num,N,L)
when N =:=1 ->
Pid = spawn(fun()->child_proces(F,X1,Width,Num-(Cores-1)*Num_Per_Core,0,N) end),
Father = self(),
PidR = spawn(fun()->loop_control(Father,0,Cores,2) end),
sendInfo(L++[Pid]++[PidR],1,Cores,2,Cores);
creat_child_proces(F,X1,X2,Width,Num_Per_Core,Cores,Num,N,L)
->Pid=spawn(fun()->child_proces(F,X1,Width,Num_Per_Core,0,N) end),
creat_child_proces(F,X1+Width*Num_Per_Core,X2,Width,Num_Per_Core,Cores,Num,N-1,L++[Pid]).
%子进程求部分和
child_proces(F,X1,Width,0,Sum,N1) -> io:format("~p ‘s result is ~p~n",[self(),Sum]),
loop_send_get(Sum);
child_proces(F,X1,Width,N,Sum,N1) -> S=(F(X1)+F(X1+Width))*Width/2,
child_proces(F,X1+Width,Width,N-1,Sum+S,N1).
%子进程部分和的发送和接收,由主进程sendInfo方法控制
loop_send_get(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(Sum+Sum1);
{Pid,Father,PidR} ->
Pid!{self(),Sum,Father,PidR}
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 -> io:format("over~n");
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.
时间: 2024-09-29 09:42:07