سؤال

أنا جديد جدا على Erlang وأنا أقرأ حاليا كتاب جو أرمسترونغ، والفصل "البرمجة المتزامنة". أحاول تشغيل قائمة بالعمليات لحساب ما إذا كان الرقم هو طريقة رئيسية (طريقة ساذجة). لكن التعليمات البرمجية الخاصة بي كما لو كانت هناك عمليات. كلا الطريقتين لها نفس المدة. أين أنا مخطئ؟

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.

شكرًا،

بيير. بيير

هل كانت مفيدة؟

المحلول

في القوائم الخاصة بك: foreach call في الكتلة الثانية، أنت تتصل RESULT=prime:is_prime(ProcId,N), ، الذي يفعل receive نتيجة لذلك. لذلك، أنت تخفيف عملية ثم انتظر حتى ينتهي حتى تفرخ العملية التالية. لهذا السبب يستغرق الأمر نفس الوقت مثل النهج الواحد الخيطي: كلا الاتجاهين، أنت تفعل واحدة فقط في وقت واحد.

بدلا من ذلك، تحتاج إلى تفرخ جميع العمليات أولا (باستخدام شيء مثل lists:map لتتبع جميع البلوز) ثم انتظر النتائج في خطوة منفصلة. لاحظ أن هذا يعني أنك يجب أن تقسم 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