[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