Question

Je suis très nouveau pour Erlang et je lis actuellement le livre de Joe Armstrong, « programmation concurrente » chapitre. Je suis en train d'exécuter une liste de processus pour calculer si un nombre est un nombre premier (méthode naïve). Mais mon code fonctionne comme s'il n'y avait pas de processus. Les deux méthodes ont la même durée. Où suis-je tort?

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().

fichier 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.

Merci,

Pierre

Était-ce utile?

La solution

Dans vos listes: appel foreach dans le deuxième bloc, vous appelez RESULT=prime:is_prime(ProcId,N), qui est en train de faire un receive pour le résultat. Donc, vous fraye un processus et puis d'attendre qu'elle se termine jusqu'à ce que vous frayer le processus suivant. Voilà pourquoi il prend la même quantité de temps que l'approche mono-thread. Dans les deux sens, vous faites une seule à la fois

, vous avez besoin au lieu de reproduire tous les processus d'abord (en utilisant quelque chose comme lists:map de garder une trace de tous les PIDS), puis attendre les résultats dans une étape séparée. Notez que signifie que vous devrez diviser la partie ProcessID ! {self(),Number} de la partie receive afin que peut être fait dans la première étape, sinon vous fraie juste un tas de processus inactifs.

Alors, quelque chose comme:

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.

Note:. Ce n'est pas testé, donc il peut avoir besoin de quelques ajustements

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top