クイックソート

30分プログラム、その121。Erlangで並行に計算するクイックソート

ピポットの右と左を別のプロセスで計算してから、あとから結合するようにしてみた。
でも、普通のクイックソートに負けている気がする。

使い方

> qsort:qsort([]).
[]

> qsort:qsort([3,2,1]).
[1,2,3]

あと、ベンチマーク用の関数も作った。それぞれ、CPU時間と経過時間を計測。対象とするリストは、すでにソート済のものを使用。

> qsort:bench(1000).
time 200(314) ms 
ok
> qsort:bench(2000).
time 490(745) ms 
ok
4> qsort:bench(3000).
time 950(1370) ms 
ok
5> qsort:bench(4000).
time 1560(2249) ms 
ok

あれ?O(N^2)で増加してる?それに、RubyのArray#sortより全然遅い。

ソースコード

-module(qsort).
-compile(export_all).

split(P,L) ->
    {[X || X<-L,X <  P],
     [X || X<-L,X >= P]}.

wait(Pid) -> 
    receive 
	{Pid,X} -> X;
	Any -> exit(Any)
    end.

send(L) ->
     Pid  = spawn(fun qsort/0),
     Pid ! {self(),L},
     Pid.

qsort() ->
    receive
 	{Pid,[]} ->
 	    Pid ! {self(),[]};
 	{Pid,[P|T]} -> 
	    {Lhs,Rhs} = split(P,T),
 	    Pid ! {self(),wait(send(Lhs)) ++ [P] ++wait(send(Rhs))};
	Any -> exit(Any)
    end.

qsort(L)->
    wait(send(L)).

bench(N)->
    statistics(runtime),
    statistics(wall_clock),
    qsort(lists:seq(0,N)),
    {_,Time1} = statistics(runtime),
    {_,Time2} = statistics(wall_clock),
    io:format("time ~p(~p) ms ~n",[Time1,Time2]).