[erlang-questions] value of spawned function

Zvi exta7@REDACTED
Sun Sep 21 13:00:48 CEST 2008


Jason, thanks.
Your example is something I had in mind.

But my rant was about impurity/assymetry of Erlang API, i.e.:
1. erlang:spawn, without erlang:join
2. Erlang is multiparadigm language, so Actors implemented using functions,
so even if functions return values, actors/processes does not. So to return
value we need a wrapper fun and a sending a message.

For me Actors/message passing is a assembler of concurrent programming.
There is a need for standard framework for higher level models: 
* Task-level parallel:  Fork-Join,  Manager-Workers (aka Master-Slave - pool
and slave modules?)
* Data-parallel:  parallel list comprehensions,  plists module, Map/Reduce

But your solution still have some problems, like quickly reaching process
limit for real life tasks and crushing BEAM. So instead of spawning Erlang
process for each subtask, I need to implement scheduler processes per core.
I trying to implement general Fork-Join framework, like this one:

Result solve(Problem problem) {    
          if (problem is small)        
               directly solve problem   
          else {       
              split problem into independent parts        
              fork new subtasks to solve each part        
              join all subtasks        
             compose result from subresults    
         }
}

(see  http://www.infoq.com/news/2007/07/concurrency-java-se-7)

See my implemenation of parallel quicksort and mergesort using your forkjoin
code.

Zvi



-module(forkjoin).
-compile(export_all).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
forkjoin(FunList) when is_list(FunList) ->
    process_flag(trap_exit, true),
    ParentPid = self(),
    % fork
    PidList = [spawn_link(
		 fun () -> 
			 ParentPid ! {'RESULT', self(), Fun()}
		 end)
	       ||
		  Fun <- FunList],
    % join
    [receive
         {'RESULT', Pid, Result} ->
             {ok, Result};
         {'EXIT', Pid, Reason} ->
             {error, Reason}
     end ||
        Pid <- PidList].

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
pqsort([]) -> [];
pqsort([X]) -> [X];                      %not necessary - optimization
pqsort([X,Y]) when X<Y -> [X,Y]; %not necessary - optimization
pqsort([X,Y]) -> [Y,X];                 %not necessary - optimization
pqsort([H|T]) ->
    [{ok,L1},{ok,L2}] = forkjoin([fun() -> pqsort([X || X<-T, X<H])  end, 
                                                fun() -> pqsort([X || X<-T,
X>=H]) end]),
    L1++[H | L2].

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
pmergesort([]) -> [];
pmergesort([X]) -> [X];                      %not necessary - optimization
pmergesort([X,Y]) when X<Y -> [X,Y]; %not necessary - optimization
pmergesort([X,Y]) -> [Y,X];                 %not necessary - optimization
pmergesort(L) when is_list(L) ->
    {L1,L2} = lists:split(length(L) div 2,L),
    [{ok,SL1},{ok,SL2}] = forkjoin([fun() -> pmergesort(L1) end, 
                                                    fun() -> pmergesort(L2)
end]),
    merge(SL1,SL2).

% merge two sorted lists
merge(L1,[]) -> L1;
merge([],L2) -> L2;
merge([H1|T1],[H2|T2]) when H1<H2 ->
    [H1|merge(T1,[H2|T2])];
merge([H1|T1],[H2|T2])  -> 
    [H2|merge([H1|T1],T2)].



-- 
View this message in context: http://www.nabble.com/value-of-spawned-function-tp19573059p19593397.html
Sent from the Erlang Questions mailing list archive at Nabble.com.




More information about the erlang-questions mailing list