Pregunta

Estoy muy nuevo en Erlang y actualmente estoy leyendo el libro de Joe Armstrong, el capítulo 'programación concurrente'. Estoy tratando de ejecutar una lista de procesos para calcular si un número es un (método ingenuo) prime. Pero mi código se ejecuta como si no hubiera ningún proceso. Ambos métodos tienen la misma duración. Dónde estoy mal?

shell.erl:

c(prime).

%a list of primes
NUMS=[102950143,102950143,102950143,102950143,102950143].

%time start
NOW1=now().
io:fwrite("Monothread~n").

%for each number test if it is a prime
lists:foreach( fun(N)->
    RESULT=prime:is_prime(N),
    io:fwrite("Result N=~p ~n",[RESULT])
    end, NUMS).
%display the duration
io:fwrite("Duration N=~p ~n",[timer:now_diff(now(),NOW1)/1.0e6]).

%time start
NOW2=now().
io:fwrite("Multithread~n").
%for each number, spawn a new process and test if it is a prime
lists:foreach( fun(N)->ProcId = prime:start(),
    io:fwrite("Calculating : procId=~p N=~p ~n",[ProcId,N]),
    RESULT=prime:is_prime(ProcId,N),
    io:fwrite("Result N=~p ~n",[RESULT])
    end, NUMS).
%display the duration   
io:fwrite("Duration N=~p ~n",[timer:now_diff(now(),NOW2)/1.0e6]).

halt().

archivo prime.erl:

-module(prime).
-export([start/0,is_prime/1,is_prime/2]).
%run the forever_function
start()->spawn(fun forever_function/0).

%catch the queries
forever_function()->
    receive
        { From,Number} -> From! is_prime(self(),2,Number),
        forever_function()
    end.

%monothreaded function
is_prime(Number)->is_prime(self(),2,Number).

%multithreaded function
is_prime(ProcessID,Number)->
    ProcessID ! {self(),Number},
    receive
        RESULT->RESULT
    end.

%recursive function scanning all the numbers from 2 to Number
is_prime(ProcessID,Div,Number)->
    if
        Div =:= Number -> {{number,Number},{prime,true}};
        Number rem Div =:= 0 -> {{number,Number},{prime,false}};
        true-> is_prime(ProcessID,Div+1,Number)
    end.

Gracias,

Pierre

¿Fue útil?

Solución

En sus listas: foreach llamada en el segundo bloque, que está llamando RESULT=prime:is_prime(ProcId,N), que está haciendo un receive para el resultado. Por lo tanto, usted está lanzando un proceso y luego esperar a que termine hasta que desovan al siguiente proceso. Es por eso que se necesita la misma cantidad de tiempo que el enfoque de un único subproceso:. En ambos sentidos, sólo se están haciendo uno a la vez

En lugar de ello, es necesario generar todos los procesos en primer lugar (usando algo como lists:map para realizar un seguimiento de todos los PID) y luego esperar los resultados en un paso separado. Nótese que significa que tendrá que dividir la parte ProcessID ! {self(),Number} de la parte receive de manera que se puede hacer en el primer paso, de lo contrario sólo está generando un montón de procesos inactivos.

Por lo tanto, algo como:

Pids = lists:map( fun(N)-> ProcId = prime:start(N),
    io:fwrite("Calculating : procId=~p N=~p ~n",[ProcId,N]),
    ProcId end, NUMS).
lists:foreach( fun(ProcId) -> {N,RESULT}=prime:is_prime(ProcId),
    io:fwrite("Result procId=~p N=~p Result=~p ~n", [ProcId,N,RESULT]) end, Pids).

start(N)->spawn(?MODULE, forever_function, [N]).

forever_function(Number)->
    Result = is_prime(self(),2,Number),
    receive
        { From, get_result } -> From! {Number,Result},
        % unnecessary since we never call this Pid again, but do it anyway :)
        forever_function()
        % could also add more cases here to set the number
        % or even do a one-shot function like before
    end.

%multithreaded function
is_prime(ProcessID)->
    ProcessID ! {self(),get_result},
    receive
        RESULT->RESULT
    end.

Nota:. Esto no se ha probado, por lo que puede necesitar algunos ajustes

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top