erlang 實現psrs 並行排序演算法

2021-07-02 15:42:35 字數 4549 閱讀 7751

-module (psrs).

-export ([start/2,handle/1]).

% 測試資料:psrs:start([15,46,48,93,39,6,72,91,14,36,69,40,89,61,97,12,21,54,53,97,84,58,32,27,33,72,20],3).

% 將資料分給各個程序,並建立

nodecreater(,pids) -> pids;

nodecreater([hlist|tlists],pids) ->

pid = spawn(?module,handle,[hlist]),

nodecreater(tlists,[pid|pids]).

% 將列表data 分成m份均勻的子列表

divlist(data,m) ->

len = lists:flatlength(data),

perlen = len div m,

dividing(data,perlen,).

dividing(data,perlen,t) ->

sublist = lists:sublist(data, perlen),

len = lists:flatlength(data),

if perlen < len ->

newdata = lists:sublist(data,perlen+1,lists:flatlength(data)-perlen),

dividing(newdata,perlen,[sublist|t]);

true ->

[sublist|t]

end.

% 將程序號列表 告知 所有程序

sendpids(pids,[h]) -> h ! ;

sendpids(pids,[h|t]) ->

h ! ,

sendpids(pids,t).

% 對資料進行取樣

getsample(mypart,m) ->

len = lists:flatlength(mypart),

perlen = len div m,

getsamples(mypart,perlen,).

getsamples(mypart,perlen,t) ->

[h|_t] = mypart,

len = lists:flatlength(mypart),

if perlen < len ->

newdata = lists:nthtail(perlen,mypart),

getsamples(newdata,perlen,[h|t]);

true ->

[h|t]

end.

% 接收其他程序的樣本

receivesample(0,sample) -> sample;

receivesample(m,sample) ->

receive

->

end.

% 從選出的樣本中找到新的樣本

finditem(data,m) ->

len = lists:flatlength(data),

perlen = len div (m+1),

newdata = lists:sublist(data,perlen+1,len-perlen),

finditems(newdata,perlen,).

finditems(data,perlen,t) ->

[h|_t] = lists:sublist(data,perlen),

len = lists:flatlength(data),

if perlen < len ->

newdata = lists:sublist(data,perlen+1,len-perlen),

finditems(newdata,perlen,[h|t]);

true ->

[h|t]

end.

% 告知其他程序主元

senditems(_items,) -> senditemsdone;

senditems(items,[hid|pids]) ->

hid ! ,

senditems(items,pids).

% 按主元進行劃分

partlist(mypart,items) ->

parting(mypart,items,).

parting(lastpart,,t) -> [lastpart|t];

parting(mypart,[h|items],t) ->

= ,parting(lastpart,items,[newpart|t]).

% 全域性交換列表,分成兩步先傳送完自己持有的列表,然後再開始接收

swap(lists,pids) ->

swapsend(lists,lists:reverse(pids)),

swapreceive(lists:flatlength(pids),).

% 傳送: 逐個取出各個列表和各個pid ,將對應列表發給對應程序

swapsend(,) -> swapdone;

swapsend([hlist|newpartlist],[hids|pids]) ->

hids ! ,

swapsend(newpartlist,pids).

% 接收

swapreceive(0,r) -> r;

swapreceive(m,r) ->

receive

->

swapreceive(m-1,[otherlist|r])

end.

% 對排好序的小列表的列表 進行歸併排序

merge_sort(sortedlists) ->

lists:sort(newlist).

% 逐次給輔助程序傳送輸出訊號

merge_inorder(,r) ->r;

merge_inorder([hid|pids],r) ->

receive

->

end.

% 主程序 與輔助程序的區別 主要在取樣 是由主程序做,以及其他協調工作

start(data,m) ->

% 均勻劃分

[firstpart|partlists] = lists:reverse(divlist(data,m)),

%io:format("~w~n",[firstpart|partlists]),

% 建立其他輔助程序

pids = nodecreater(partlists,),

% 使全部程序都知道其他程序的程序號,後來的全域性交換需要

sendpids([self()|pids],pids),

sortlist = lists:sort(firstpart),

sample = getsample(sortlist,m),

% 接收其他程序的樣本,排序選出主元

newsample = receivesample(m-1,sample),

sortsample = lists:sort(newsample),

items = lists:reverse(finditem(sortsample,m-1)),

% 告知其他程序主元

senditems(items,pids),

% 按主元進行劃分

newpartlist = partlist(firstpart,items),

% 全域性交換

sortlists = swap(newpartlist,[self()|pids]),

newsortlist = merge_sort(sortlists),

result = merge_inorder(pids,newsortlist),

io:format("~w~n",[result]).

% 輔助程序

handle(mypart) ->

sortlist = lists:sort(mypart),

% 接受其他程序的pids

receive

->

[master|_pids] = ppids

end,

m = lists:flatlength(ppids),

% 找出樣本

sample = getsample(sortlist,m),

% 向主程序傳送樣本

master ! ,

% 接收主程序篩選出的主元

receive

->

items

end,

newpartlist = partlist(mypart,items),

% 全域性交換

sortlists = swap(newpartlist,ppids),

% 歸併排序

erlang 實現並行快速排序

在保證尾遞迴的情況下,使用乙個輔助函式 handl 對parallel qsort進行包裝,則parallel qsort只管 分發任務即可,計算好了 再進行樹形通訊合併,之前一直在糾 結於是不是要使用程序字典,來儲存有哪些程序,程序字典,在erlang program一書中,不建議採用,因為其提供...

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...

Erlang 並行梯度積分法

這個 寫了兩天,從沒思路到有思路,還好最終搞定了 不過這個程序數必須為2 n個。先貼乙個執行截圖 子程序求部分和 child proces f,x1,width,0,sum,n1 io format p s result is p n self sum loop send get sum child...