Erlang kpmap 함수

pmap을 개선해서 kpmap함수를 만들어 봤다. (함수명은 내가 직접 지어본거다. ^^;)

kpmap 함수는 …
기존의 pmap함수가 입력되는 리스트 원소 갯수만큼 process를 만들어 버리는 단점을 가지고 있기 때문에 마지막 인수로 k라는 인수를 두어 k개의 process만을 만들어 처리를 하게끔 하는 함수이다.

pmap 함수에서 내가 사용했던 작업이 1000여개의 파일을 열어 텍스트 처리를 하는 함수였는데, 1000여개의 함수를 여는 1000여개의 process를 만들기가 매우 부담스러웠다. 또한 리스트에 얼마나 많은 데이터가 있을지도 모르고 어떤 성격의 처리를 해야 할지 모르는 상황에서 무작정 리스트 원소 갯수만큼의 프로세스를 만드는것도 문제인거 같기도 하고 말이다.

그래서 만들어 봤다… kmap함수!

[CODE js]
kpmap(F, L ,K) ->
    S = self(),
    Ref = erlang:make_ref(),
    Splitted_list = split(L, K),
    foreach(fun(I) ->
            spawn(fun() -> do_f2(S, Ref, F, I) end)
        end, Splitted_list),
    %% gather the result
    gather1(length(L), Ref, []).

do_f2(Parent, Ref, F, I) ->
    Parent ! {Ref, (catch lists:map(F, I))}.
   
gather1(0, _, L) -> L;

gather1(N, Ref, L) ->
    receive
        {Ref, Ret} ->
            gather1(N-1, Ref, lists:append(Ret, L))
    end.

split(L, Num) ->
    if
        length(L) < Num ->
            split(L, Num, 1);
        true ->
            split(L, Num, length(L) div Num)
    end.

split(L, Num, Len) ->
    case lists:split(Len,L) of
        {First, Second} ->
            if
                (length(Second) < Len) or (Num == 1) ->
                    [First ++ Second];
                true ->
                    [First|split(Second, Num – 1, Len)]
            end
    end.
[/CODE]

위에서 split 함수는 N개의 원소를 가지는 리스트를 K개의 sublist로 쪼개준다.

 각 sub process에서 결과 리스트를 반환하는데, 모든 결과가 나올때까지 대기해서 한번에 결과를 리턴하는게 나을지, 아니면 결과가 나올때마다 보내는게 나을지는 잘 모르겠다. 이 부분에 대해서 확인해 보려면 erlang 프로세스간의 통신이 어떻게 이루어지는지 확인해본 다음에야 확답이 가능할거 같다.

0 0 votes
Article Rating
Subscribe
Notify of
guest

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
daybreaker

MPI 쪽에서는 같은 작업은 MPI_Scatter와 MPI_Gather라는 함수를 이용해서 할 수 있고, 데이터를 나누어 보내거나 합칠 때도 linear time이 아닌 log time에 할 수 있는 것으로 알고 있습니다.
어쨌든 언어 차원에서 저런 걸 지원한다는 게 흥미롭네요.