%在保证尾递归的情况下,使用一个辅助函数 handl 对parallel_qsort进行包装,则parallel_qsort只管 分发任务即可,计算好了 再进行树形通信合并,之前一直在纠%结于是不是要使用进程字典,来保存有哪些进程,进程字典,在erlang program一书中,不建议采用,因为其提供了共享数据的可能,破坏了erlang的设计原则,erlang是面向消息的语言,进行间通信只能通过消息。<pre name="code" class="plain">-module (parallel_qsort).
-export ([start/2,handle/5]).
% 测试数据
% parallel_qsort:start([11,3,2,8,9,4,10,23,45,100,15,0,-1,47,9,32,12,64,5,35,79,77,27,1,6,7],8).
% parallel_qsort:start([11,3,2,8,9,4,33,34,34,10,23,45,100,15,0,-1,47,9,32,12,64,5,35,79,77,27,1,6,7],8).
% 启动线程的工作
% 1.启动 各个执行线程
start (Data ,M) ->
io:format("Len : ~w~n",[lists:flatlength(Data)]),
spawn(?MODULE,handle,[Data,M,M,1,self()]).
% 包装parallel_qsort,和合并结果的操作
handle(Data,M,Processnum,Id,Master) ->
io:format("Id ~w~n",[Id]),
{Pids,Res} = parallel_qsort(Data,M,Processnum,Id,Master,[self()]),
merge_wait(Res,Master,Id,2,Processnum,Pids).
% 通过Id 判断 改发还是改接,Master 是要发给的进程 ,M是递归的轮数
merge_wait(Res,Master,Id,Judge,M,Pids) when M =:= 1 ->
io:format("result : ~w :~w ~n",[Res,lists:flatlength(Res)]);
merge_wait(Res,Master,Id,Judge,M,[Hid|Tids]) ->
if Id rem Judge =:= 1 ->
receive
{res,Hid,OtherRes} -> %不能判断接收的顺序
NewRes = lists:append(Res,OtherRes),
io:format("receive: ~w ~w ~n",[Id,NewRes]),
merge_wait(NewRes,Master,Id,Judge*2,M div 2,Tids)
end;
true ->
io:format("send from ~w ~w ~n",[Id,Res]),
Master ! {res,self(),Res}
end.
% 划分 分发任务
% 直到 列表很小或者M=0(没有单独核来跑进程) 串行排序
% 此时 将自己的结果和Id发回主线程
parallel_qsort(Data,M,Start,Id,Master,Pids) ->
Len = lists:flatlength(Data),
if M =:= 1->
NewData = lists:sort(Data),
io:format("get ~w ~w ~n",[Id,NewData]),
{Pids,NewData};
true ->
{FrontPart,BehindPart} = partition(Data),
% io:format("~w:~w ~n",[FrontPart,BehindPart]),
Pid = spawn(?MODULE,handle,[BehindPart,(M div 2),Start,Id+(M div 2),self()]),
parallel_qsort(FrontPart,M div 2,Start,Id,Master,[Pid|Pids])
end.
partition([]) -> {[],[]};
partition([H|T]) when T =:= []-> {[H],[]} ;
partition([H|T]) ->
{[X || X <- [H|T] , X =< H],[Y || Y <- T , Y > H]} .
erlang 实现并行快速排序
最新推荐文章于 2018-11-29 10:20:45 发布