自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Erlang并行快速排序?qū)崙?zhàn)

開發(fā) 開發(fā)工具
我們今天將談談Erlang多進程方式實現(xiàn)快速排序,通過對比快速排序的串行算法,我們將此串行算法改進為并行算法。

本節(jié)我將用Erlang多進程方式實現(xiàn)快速排序,快速排序采用的是分治的思想,即將原問題分解為若干個規(guī)模更小但結(jié)構(gòu)與原問題相似的子問題。遞歸地解這些子問題,然后將這些子問題的解組合為原問題的解。通過對比快速排序的串行算法,我們將此串行算法改進為并行算法。

首先,來看看快速排序的串行算法:

1.從數(shù)列中挑出一個元素,稱為 "基準"(pivot);

2.重新排序數(shù)列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的后面(相同的數(shù)可以到任一邊)。在這個分割結(jié)束之后,該基準就處于數(shù)列的中間位置。這個稱為分割(partition)操作;

3.遞歸地(recursive)把小于基準值元素的子數(shù)列和大于基準值元素的子數(shù)列排序。

此思想網(wǎng)上到處都有,現(xiàn)在來看看快速排序的并行算法:

其中的一個簡單思想是,對每次劃分過后得到的兩個序列分別使用兩個處理器完成遞歸排序。例如對一個長為n的序列,首先劃分得到兩個長為n/2的序列,將其交給兩個處理器分別處理;而后進一步劃分得到四個長為n/4的序列,再分別交給四個處理器處理:如此遞歸下去最終得到排序好的序列。

  當然,這里是理想的劃分情況,如果劃分步驟不能達到平均分配的目的,那么排序效率會相對較差。

  跟上節(jié)講得并行枚舉排序進程調(diào)用的區(qū)別在于,枚舉排序一次性將數(shù)據(jù)傳給所有節(jié)點進程,而快速排序進程調(diào)用在分割數(shù)據(jù)的過程中呈現(xiàn)的是樹狀形式。

  并行快排的偽代碼如下:

  1.  //快速排序的并行算法  
  2.    
  3.  輸入:無序數(shù)組data[1,n],使用的處理器個數(shù)為2^m  
  4.  輸出:有序數(shù)組data[1,n]  
  5.    
  6.  Begin  
  7.       para_quicksort(data,1,n,m,0)  
  8.  End  
  9.    
  10. procedure para_quicksort(data,i,j,m,id)  
  11. Begin  
  12.     if (j-i) <=k or m=0 then   
  13.           Pid call quicksort(data,i,j)  
  14.     else 
  15.           Pid:r = patition(data,i,j)  
  16.           Pid send data[r+1,m-1] to Pid+2 ^(m-1)  
  17.           para_quicksort(data,i,r-1,m-1,id)  
  18.           par_quicksort(data,r+1,j,m-1,id+2^(m-1) )  
  19.           Pid+2 ^ (m-1) send data[r+1,m-1] back to Pid  
  20.     end if 
  21. End 

現(xiàn)在,就來看看Erlang代碼實現(xiàn)并行快排:

  設置啟動接口,啟動多個進程之后,在總控端調(diào)用Dict = store(['node1@pc1305','node2@pc1305']...)存儲各節(jié)點進程的字典表,然后調(diào)用start([3,4,512,1,2,5,……],2,Dict)進行快排,其中第二參數(shù)表示需要最多2^2=4個進程來完成任務,總控端也作為一個排序的節(jié)點。

  1.  %% 啟動排序時,需存儲各節(jié)點信息:使用Dict = store(['node1@pc1305','node2@pc1305']...)方法  
  2.  %%然后,便可啟動start(Data,M,Dict) 進行排序,M為啟動的進程個數(shù)指標,Dict為上述存儲的節(jié)點  
  3.    
  4.  -module(para_qsort).  
  5.  -export([para_qsort/3,start/3,store/1,lookup/2]).  
  6.    
  7.  store(L) -> store(L,[]).  
  8.    
  9.  store([],Ret) -> Ret;  
  10. store(L,Ret) ->  
  11.     Value = lists:nth(1,L),  
  12.     Key = length(Ret)+1,  
  13.     io:format("Key=~p Value=~p~n",[Key,Value]),  
  14.     New = [{Key,Value} | Ret],  
  15.     store(lists:delete(Value,L) , New).  
  16.       
  17. lookup(Key,Dict) ->  
  18.     {K,V} = lists:nth(1,Dict),  
  19.     if 
  20.         K =:= Key ->  
  21.             V;  
  22.         K =/= Key ->  
  23.             Filter = lists:delete({K,V},Dict),  
  24.             lookup(Key,Filter)  
  25.     end.  
  26.  
  27. start(Data,M,Dict) ->   
  28.     register(monitor, spawn(fun() -> wait([]) end)),  
  29.     put(monitor, node()),  
  30.     NewDict = [{monitor, get(monitor)} | Dict],  
  31.     para_qsort(Data,M,NewDict). 

  wait/1函數(shù)主要對各節(jié)點排序好的結(jié)果進行歸并整理,然后輸出最終結(jié)果,代碼如下

  1.  %%服務器節(jié)點監(jiān)聽  
  2.  wait(Ret) ->  
  3.      Len1 = parser(Ret)+length(Ret)-1,  
  4.      Len2 = len(Ret),  
  5.      if 
  6.          (Len1 =:= Len2) and  (Len2 =/=0) ->  
  7.              SortRet= merge(Ret,[],1),  
  8.              io:format("Para qsort result:~n",[]),  
  9.              io:format("~p~n",[SortRet]);  
  10.         (Len1 =/= Len2) or (Len2 =:= 0) ->  
  11.             receive  
  12.                 {Node,Pid,L} ->  
  13.                     {Data,I,J} = L,  
  14.                     Temp = [{Node,Data,I,J}|Ret],  
  15.                     wait(Temp)  
  16.             end;  
  17.               
  18.         die ->  
  19.             quit  
  20.     end.  
  21.  
  22. len([]) -> 0;  
  23. len([H|T])->  
  24.     {Node,Data,I,J} = H,  
  25.     length(Data).  
  26.  
  27. parser([]) -> 0;  
  28. parser([H|T]) ->  
  29.     {Node,Data,I,J}=H,  
  30.     J-I+1+parser(T).  
  31.  
  32. merge([],Ret,Len) -> Ret;  
  33. merge(T,Ret,Start) ->  
  34.     H = lists:nth(1,T),  
  35.     {Node,Data,I,J} = H,  
  36.     if 
  37.         I =:= Start ->  
  38.             ListBetween = lists:sublist(Data,I, J-I+1),  
  39.             case (I=:=1) of  
  40.                 true ->  
  41.                     Temp = lists:append(Ret,ListBetween);  
  42.                 false ->  
  43.                     Pivo = lists:append(Ret,[lists:nth(I-1,Data)]),  
  44.                     Temp = lists:append(Pivo,ListBetween)  
  45.             end,  
  46.             io:format("~n-----<< ~p >> processing data[~p,~p]~n-------------------------Result=~p~n",[Node,I,J,Temp]),  
  47.             Len = Start+J-I+2,  
  48.             NewData = lists:delete(H,T),  
  49.             merge(NewData,Temp,Len);  
  50.         I =/= Start ->  
  51.             NewData = lists:delete(H,T),  
  52.             Temp = lists:append(NewData,[H]),  
  53.             merge(Temp,Ret,Start)  
  54.     end. 

para_qsort完成對排序任務的分發(fā),代碼如下:

  1. para_qsort(Data,M,Dict) ->  
  2.     %%進程個數(shù)最多為2^M次方  
  3.     I = 1,   
  4.     J = length(Data),  
  5.     ID = 0,  
  6.     para_qsort(Data,I,J,M,ID,Dict).  
  7.  
  8. para_qsort(Data,I,J, M, ID,Dict) ->  
  9.     %% 閥值,列表排序個數(shù)小于K時直接調(diào)用qsort直接快排  
  10.    K = 4,   
  11.    Value1 = (J-I) < K,  
  12.    Value2 = (M =:= 0),  
  13.    Value = Value1 or Value2,  
  14.    if 
  15.        Value =:= true  ->  
  16.            %io:format("~nCurrent node: (~p) ~nData= ~p  I=~p  J=~p~n",[node(),Data,I,J]),  
  17.            ListBefore = lists:sublist(Data, I-1),  
  18.            ListBetween = lists:sublist(Data,I, J-I+1),  
  19.            ListAfter = lists:sublist(Data,J+1,length(Data)-J),  
  20.            Ret = lists:sort(ListBetween),  
  21.            Temp = lists:append(ListBefore,Ret),  
  22.            NewData =  lists:append(Temp, ListAfter),  
  23.            {monitor, lookup(monitor,Dict) } ! {node(),self(),{NewData,I,J} },  
  24.            io:format("-------------------------------------------------------------");  
  25.        Value =:= false  ->  
  26.            {NewData,R} = partition(Data,I,J),  
  27.            send(NewData, R+1, J, M-1,ID + math:pow(2 ,(M-1)), Dict ),  
  28.            para_qsort(NewData,I,R-1,M-1,ID, Dict)  
  29.    end. 

  其中patition用于將data按基準值劃分為兩部分,代碼如下:

  1. partition(Data, K, L) ->  
  2.     Pivo= lists:nth(L, Data),  
  3.     ListBefore = lists:sublist(Data, K-1),  
  4.     ListBetween = lists:sublist(Data,K, L-K),  
  5.     ListAfter = lists:sublist(Data,L+1,length(Data)-L),  
  6.     Left = [X|| X <- ListBetween,X =<Pivo],  
  7.     Right = [X || X <- ListBetween,X > Pivo],  
  8.     Ret = lists:append(Left,[Pivo|Right]),  
  9.     Temp = lists:append(ListBefore,Ret),  
  10.    NewData =  lists:append(Temp, ListAfter),  
  11.    Len = length(ListBefore)+length(Left)+1,  
  12.    {NewData, Len}. 

任務分割完后,會將此任務發(fā)送給下個節(jié)點進程進行處理,send代碼如下:

  1. send( Data, I, J, M,No ,Dict) ->  
  2.     ID = trunc(No),  
  3.     Node = lookup(ID,Dict),  
  4.     Pid = spawn(Node, fun() -> loop() end),  
  5.     Pid ! {node(),self(), {Data,I,J,M,ID,Dict}}.  
  6.  
  7. %%客戶節(jié)點N準備接受排序數(shù)據(jù)  
  8. loop() ->  
  9.     receive  
  10.        {Node,Pid,die} ->  
  11.            disconnect_node(Node),  
  12.            io:format("Node (~p) disconnected~n",[Node]),  
  13.            quit;  
  14.        {Node,Pid,L} ->      
  15.            {Data,I,J,M,ID,Dict} = L,  
  16.            %io:format("4----:Current node:~p server node:~p~n",[node(),lookup(monitor,Dict)]),  
  17.            para_qsort(Data,I,J,M,ID,Dict)  
  18.            %loop()  
  19.    end. 

  思想比較簡單,我只是沒對它進行進一步優(yōu)化,最終運行結(jié)果如下:

  大家可以看到,此data的劃分就是不均勻的,node1、node3只處理了一個數(shù)據(jù),node2處理了3個數(shù)據(jù),其余的都是server處理的,因此排序的效率問題很差。此程序只是展示如何使用Erlang實現(xiàn)并行快排,并不是學習如何優(yōu)化問題。

  大致就說這么多了,以后我將實現(xiàn)PSRS并行算法的Erlang實現(xiàn),這個算法Erlang實現(xiàn)起來比較麻煩,大家可以先去看看。

原文:http://www.cnblogs.com/itfreer/archive/2012/05/14/Erlang_in_practise_quick-sort.html

【編輯推薦】

  1. Erlang之父Joe Armstrong訪談:程序調(diào)試與啤酒
  2. Scala和Erlang,以及多核主導的未來
  3. Erlang面向分布與并發(fā)的編程語言
  4. 看Erlang中Actor模型的執(zhí)行方式和優(yōu)劣
  5. Erlang視點:并行計算和云計算
責任編輯:彭凡 來源: 博客園
相關(guān)推薦

2012-05-08 13:42:24

Erlang

2010-03-22 14:45:40

云計算

2012-05-07 15:32:46

Erlang

2009-08-19 09:42:34

F#并行排序算法

2011-04-20 15:20:03

快速排序

2014-10-30 15:14:54

快速排序編程算法

2009-08-13 10:35:05

Scala數(shù)組排序

2021-03-04 07:24:28

排序算法優(yōu)化

2011-05-25 11:25:23

快速排序Javascript

2010-09-17 14:13:20

SIP業(yè)務Erlang

2009-11-20 09:24:10

PHP多維數(shù)組排序

2014-10-30 15:08:21

快速排序編程算法

2021-01-26 05:33:07

排序算法快速

2023-03-07 08:02:07

數(shù)據(jù)結(jié)構(gòu)算法數(shù)列

2023-05-08 07:55:05

快速排序Go 語言

2014-03-03 16:44:57

算法

2013-12-18 11:04:57

CPU雙核

2022-03-07 09:42:21

Go快速排序

2022-10-10 08:13:16

遞歸通用代碼

2022-03-22 08:24:10

冒泡排序算法JS
點贊
收藏

51CTO技術(shù)棧公眾號