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 프로세스간의 통신이 어떻게 이루어지는지 확인해본 다음에야 확답이 가능할거 같다.
Erlang kpmap 함수 by from __future__ import dream is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.