문제

나는 Erlang을 처음 접했고 현재 Joe Armstrong의 저서 인 'Concurrent Programming'을 읽고 있습니다. 숫자가 프라임 (순진한 방법)인지 계산하기 위해 프로세스 목록을 실행하려고합니다. 그러나 내 코드는 프로세스가없는 것처럼 실행됩니다. 두 방법 모두 동일한 지속 시간이 있습니다. 내가 어디에 틀렸어?

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

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

감사,

피에르

도움이 되었습니까?

해결책

귀하의 목록에서 : 두 번째 블록의 Foreach Call, 당신은 RESULT=prime:is_prime(ProcId,N),, 그것은 a receive 결과를 위해. 따라서 프로세스를 산란 한 다음 다음 프로세스를 생성 할 때까지 끝날 때까지 기다리고 있습니다. 그렇기 때문에 단일 스레드 접근 방식과 같은 시간이 걸리는 이유입니다. 두 가지 방법 모두 한 번에 한 번만하고 있습니다.

대신, 모든 프로세스를 먼저 스폰해야합니다 ( 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.

참고 : 이것은 테스트되지 않았으므로 약간의 조정이 필요할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top