1

私はErlangを初めて使用し、現在JoeArmstrongの本「並行プログラミング」の章を読んでいます。プロセスのリストを実行して、数値が素数であるかどうかを計算しようとしています(単純な方法)。しかし、私のコードはプロセスがないかのように実行されます。どちらの方法も同じ期間です。私はどこが間違っていますか?

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

ファイル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.

ありがとう、

ピエール

4

1 に答える 1

12

2番目のブロックのlists:foreach呼び出しでは、結果に対してをRESULT=prime:is_prime(ProcId,N)実行しているを呼び出しています。receiveつまり、プロセスを生成し、次のプロセスを生成するまでプロセスが終了するのを待ちます。そのため、シングルスレッドアプローチと同じ時間がかかります。どちらの方法でも、一度に1つしか実行しません。

代わりに、最初にすべてのプロセスを生成し(lists:mapすべてのPIDを追跡するなどを使用して)、次に別のステップで結果を待つ必要があります。ProcessID ! {self(),Number}つまり、最初のステップで実行できるように、パーツをパーツか​​ら分割する必要がありreceiveます。そうしないと、アイドル状態のプロセスが大量に生成されます。

だから、次のようなもの:

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.

注:これはテストされていないため、微調整が必​​要な場合があります。

于 2009-12-06T14:24:59.507 に答える