Erlang 和进程
我对 Erlang 很陌生,目前正在阅读 Joe Armstrong 的书“并发编程”一章。我正在尝试运行一个进程列表来计算一个数字是否是素数(简单的方法)。但我的代码运行起来就好像没有进程一样。两种方法的持续时间相同。我哪里错了?
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.
谢谢,
皮埃尔
I'm very new to Erlang and I'm currently reading Joe Armstrong's book, chapter 'concurrent programming'. I'm trying to run a list of processes to calculate if a number is a prime (naive method). But my code runs as if there was no processes. Both methods have the same duration. Where am I wrong ?
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.
Thanks,
Pierre
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在第二个块中的列表:foreach 调用中,您正在调用
RESULT=prime:is_prime(ProcId,N)
,它正在对结果进行接收
。因此,您正在生成一个进程,然后等待它完成,直到生成下一个进程。这就是为什么它需要与单线程方法相同的时间:无论哪种方式,您一次只执行一项操作。相反,您需要首先生成所有进程(使用诸如
lists:map
之类的东西来跟踪所有 PID),然后在单独的步骤中等待结果。请注意,这意味着您必须拆分 ProcessID ! {self(),Number} 部分来自receive
部分,以便可以在第一步中完成,否则您只是生成一堆空闲进程。因此,类似于:
注意:这未经测试,因此可能需要一些调整。
In your lists:foreach call in the second block, you are calling
RESULT=prime:is_prime(ProcId,N)
, which is doing areceive
for the result. So, you're spawning a process and then waiting for it to finish until you spawn the next process. That's why it takes the same amount of time as the single-threaded approach: both ways, you're only doing one at a time.Instead, you need to spawn all the processes first (using something like
lists:map
to keep track of all the PIDs) and then wait for the results in a separate step. Note that means you'll have to split theProcessID ! {self(),Number}
part from thereceive
part so that can be done in the first step, otherwise you're just spawning a bunch of idle processes.So, something like:
Note: this is untested, so it may need some tweaking.