OddEvenソートの並列化
、、、を、なんとか昼休み中にやろうとしたんだけれど、時間が全然足りなかった。というかカオスった。
なんとか正常動作はしているようだけれど、馬鹿すぎる設計。
%% Author: tkuro %% Created: 2009/11/12 %% Description: odd-even parallel sort -module(oddeven_par). %% %% Include files %% -include_lib("eunit/include/eunit.hrl"). %% %% Exported Functions %% -export ([sort/1]). %% -------------------------------------------------------------------- %% Test Functions %% -------------------------------------------------------------------- sort_test_() -> [ ?_assertEqual(sort([1,3,2]),[1,2,3]), ?_assertEqual(sort([3,2,0,1,5,8,4,2,2,7]),[0,1,2,2,2,3,4,5,7,8]) ]. %% -------------------------------------------------------------------- %% Func: sort/1 %% Returns: sorted list %% -------------------------------------------------------------------- sort(L) -> make_proc_array(L). make_proc_array(L) -> make_proc_loop(none, L, true, length(L)). make_proc_loop(Last, [], _, _) -> Last ! {rememberme, last}, gather([]); make_proc_loop(Left, [H|T], Side, N) -> S = self(), Pid = spawn_link(fun () -> sorter(S, {Left, none}, H, Side, N) end), make_proc_loop(Pid, T, not(Side), N). % (reduce) gather(Acc) -> receive fin -> Acc; Val -> gather([Val|Acc]) end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% sofrter node definition %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%% sorter(S, {none, none}, Val, Side, N) -> receive {rememberme, R} -> sorter(S, {none, R}, Val, Side, N) end; % sending primary link request sorter(S, {Left, none}, Val, Side, N) when Left =/= none -> Left ! {rememberme, self()}, sorter(S, {Left, wait}, Val, Side, N); sorter(S, {Left, wait}, Val, Side, N) -> receive {rememberme, R} -> sorter(S, {Left, R}, Val, Side, N) end; % finish sorting sorter(S, Nbrs, Val, _, 0) -> case Nbrs of {Left, last} -> % Right == last means I'm the end S ! Val, Left ! report; % ask next to report {none, _} -> receive report -> S ! Val, S ! fin end; {Left, _} -> receive report -> S ! Val, Left ! report % ask next to report end end; sorter(S, Nbrs, Val, Side, N) -> {Left, Right} = Nbrs, NSide = not(Side), Dir = if Side -> Right; true -> Left end, try pushval(Dir, Val, N) of _ -> void catch freespin -> sorter(S, Nbrs, Val, NSide, N-1) end, receive {push, Left, HisVal, N} -> case Val > HisVal of true -> sorter(S, Nbrs, Val, NSide, N-1); false -> sorter(S, Nbrs, HisVal, NSide, N-1) end; {push, Right, HisVal, N} -> case HisVal > Val of true -> sorter(S, Nbrs, Val, NSide, N-1); false -> sorter(S, Nbrs, HisVal, NSide, N-1) end end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% pushval(Pid, Val, N) -> case Pid =/= last andalso Pid =/= none of true -> Pid ! {push, self(), Val, N}; false-> throw(freespin) end.
解説とかつけておいたほうがいろいろ直してもらえたりするのかな。。。パッと見ただけでも sorterのガードいらんよな、とか思うけど気力切れた。つかひどい過ぎてリファクタ不能な感じかも。
追記:
折角ラベルつけてたのに receiveでそれを見ていなかったのが原因だッてことに、休憩中にコーヒー飲んでて気がついた。上のコード修正しました。某先生に見つかったらウッ殺されそうな間違いでした。ごめんさい。ちゃんちゃん。