Erlang -奇偶并行排序
-module (exe9).
-export ([start/2,handle/4]).
% L=[2,12,14,25,31,42,43,43,13,34,34,41,41,312,352,354].
% 将数据分给各个进程,并创建
nodecreater([],Pids,M,Id,Master) ->
io:format("Pids:~w Id:~w Master:~w~n",[Pids,Id,Master]),
lists:reverse(Pids);
nodecreater([Hlist|TLists],Pids,M,Id,Master) ->
io:format("Pids:~w Id:~w Master:~w~n",[Pids,Id,Master]),
Pid = spawn(?MODULE,handle,[Hlist,M,Id,Master]),
nodecreater(TLists,[Pid|Pids],M,Id+1,Master).
% 迭代交换奇偶数据
% 策略:当M是偶数时,Id 为奇数时,此core从他后面的core接受数据,再进行排序,再将结果等分成两部分,并将后半部分返回给
% 发送者,发送者接收到数据后进入下轮迭代,本核进入下一轮迭代。
% 当M是奇数时,Id=1或者Id=Core数时,直接进入下一轮。
% id为偶数时时(除去id为1和core数时),此core从他后面的core接受数据,再进行排序,再将结果等分成两部分,并将后半部分返回给
% 发送者,发送者接收到数据后进入下轮迭代,本核进入下一轮迭代
%
loop(Data,1,Id,_FrontPid,_NextPid,CoreN) ->
io:format("Id:~w Res:~w ~n",[Id,Data]),
Data;
loop(Data,M,Id,FrontPid,NextPid,CoreN) ->
io:format("Data:~w M:~w Id:~w ~n",[Data,M,Id]),
if
% M为偶数时
M rem 2 =:= 0 ->
if
%Id为奇数
Id rem 2 =:=1 ->
receive {M,NewData,Nextid} ->
MergeData=lists:append(Data,NewData),
SortedData = lists:sort(MergeData),
LenPer=length(SortedData) div 2,
FrontData = lists:sublist(SortedData,LenPer),
TailData = lists:sublist(SortedData,LenPer+1,LenPer),
Nextid !{M,TailData,self()},
loop(FrontData,M-1,Id,FrontPid,Nextid,CoreN)
end;
%Id为偶数
true ->
FrontPid!{M,Data,self()},
receive {M,MyData,FrontPid} ->
loop(MyData,M-1,Id,FrontPid,NextPid,CoreN)
end
end;
true ->
if
(Id =:= 1) or (Id =:= CoreN) ->
loop(Data,M-1,Id,FrontPid,NextPid,CoreN);
true ->
if
Id rem 2 =:= 0 ->
receive {M,NewData,Nextid} ->
MergeData=lists:append(Data,NewData),
SortedData = lists:sort(MergeData),
LenPer=length(SortedData) div 2,
FrontData = lists:sublist(SortedData,LenPer),
TailData = lists:sublist(SortedData,LenPer+1,LenPer),
Nextid !{M,TailData,self()},
loop(FrontData,M-1,Id,FrontPid,Nextid,CoreN)
end;
true -> FrontPid!{M,Data,self()},
receive {M,MyData,FrontPid} ->
loop(MyData,M-1,Id,FrontPid,NextPid,CoreN)
end
end
end
end.
handle(MyPart,M,Id,Master) ->
% 对自己分的的数据进行排序
MyData = lists:sort(MyPart),
io:format("handle Id:~w Data:~w ~n",[Id,MyData]),
% 得到该进程后面进程的Id
receive
{next,NextPid} ->
NextPid
end,
% 得到该进程前面进程的Id
receive
{front,FrontPid} ->
FrontPid
end,
% 进行M次迭代
Res = loop(MyData,M,Id,FrontPid,NextPid,M),
Master ! {result,self(),Res}.
% 逐次接收
merge_inorder([],R) ->R;
merge_inorder([Hid|Pids],R) ->
receive
{result,Hid,Res} ->
merge_inorder(Pids,lists:append(R,Res))
end.
% 使进程知道紧接其的后续进程pid
sendnextid(Pids) ->
[Firstid|NewPids] = lists:reverse(Pids),
sendgon(NewPids,Firstid,Firstid).
sendgon([],ItsNextid,Ownid) ->
%io:format("Ownid:~w NextPid:~w~n",[Ownid,ItsNextid]),
Ownid ! {next,ItsNextid};
sendgon([Nextid|Pids],ItsNextid,Ownid) ->
%io:format("Ownid:~w NextPid:~w~n",[Ownid,ItsNextid]),
Ownid ! {next,ItsNextid},
sendgon(Pids,Ownid,Nextid).
% 使进程知道它前面的进程是什么
sendfrontid([Firstid|NewPids]) ->
sendgof(NewPids,Firstid,Firstid).
sendgof([],ItsFrontid,Ownid) ->
%io:format("Ownid:~w FrontPid:~w~n",[Ownid,ItsFrontid]),
Ownid ! {front,ItsFrontid};
sendgof([Nextid|Pids],ItsFrontid,Ownid) ->
%io:format("Ownid:~w FrontPid:~w~n",[Ownid,ItsFrontid]),
Ownid ! {front,ItsFrontid},
sendgof(Pids,Ownid,Nextid).
%将Data分成M份
divlist(Data,M)->
Len = length(Data),
PerLen = Len div M,
prodiv(Data,PerLen,M,[]).
prodiv(Data,PerLen,1,L) ->lists:reverse([Data|L]);
prodiv(Data,PerLen,M,L) ->
Len=length(Data),
Sub = lists:sublist(Data,PerLen),
Res = lists:sublist(Data,PerLen+1,Len-PerLen),
prodiv(Res,PerLen,M-1,[Sub|L]).
start(Data,M) ->
% 均匀划分
[FirstPart|PartLists] = divlist(Data,M),
io:format("after div:~n~w~n",[[FirstPart|PartLists]]),
% 创建其他辅助进程
Pids = nodecreater(PartLists,[],M,2,self()),
io:format("Pids:~w~n",[Pids]),
sendnextid([self()|Pids]),
sendfrontid([self()|Pids]),
% 主线程的ID为1,对自己的数据进行处理.
MyData = lists:sort(FirstPart),
receive
{next,NextPid} ->
NextPid
end,
receive
{front,FrontPid} ->
FrontPid
end,
FirstRes = loop(MyData,M,1,FrontPid,NextPid,M),
Result = merge_inorder(Pids,FirstRes),
io:format("~w~n",[Result]).
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。