Dan*_*Dan 6 concurrency erlang primes
我正在通过projecteuler.net上的问题来学习如何在Erlang中编程,并且我正在努力创建一个可以在不到一分钟内创建低于200万的所有素数的素数生成器.使用顺序样式,我已经编写了三种类型的生成器,包括Eratosthenes的Sieve,并且它们都没有表现得足够好.
我认为一个并发的Sieve会很好用,但我收到的是bad_arity消息,我不知道为什么.有关我遇到问题的原因或如何正确编码的任何建议?
这是我的代码,注释掉的部分是我试图让事情并发的地方:
-module(primeserver).
-compile(export_all).
start() ->
register(primes, spawn(fun() -> loop() end)).
is_prime(N) -> rpc({is_prime,N}).
rpc(Request) ->
primes ! {self(), Request},
receive
{primes, Response} ->
Response
end.
loop() ->
receive
{From, {is_prime, N}} ->
if
N From ! {primes, false};
N =:= 2 -> From ! {primes, true};
N rem 2 =:= 0 -> From ! {primes, false};
true ->
Values = is_not_prime(N),
Val = not(lists:member(true, Values)),
From ! {primes, Val}
end,
loop()
end.
for(N,N,_,F) -> [F(N)];
for(I,N,S,F) when I + S [F(I)|for(I+S, N, S, F)];
for(I,N,S,F) when I + S =:= N -> [F(I)|for(I+S, N, S, F)];
for(I,N,S,F) when I + S > N -> [F(I)].
get_list(I, Limit) ->
if
I
[I*A || A
[]
end.
is_not_prime(N) ->
for(3, N, 2,
fun(I) ->
List = get_list(I,trunc(N/I)),
lists:member(N,lists:flatten(List))
end
).
%%L = for(1,N, fun() -> spawn(fun(I) -> wait(I,N) end) end),
%%SeedList = [A || A
%% lists:foreach(fun(X) ->
%% Pid ! {in_list, X}
%% end, SeedList)
%% end, L).
%%wait(I,N) ->
%% List = [I*A || A lists:member(X,List)
%% end.
我使用Go和渠道编写了一个Eratosthenesque并发主筛.
这是代码:http://github.com/aht/gosieve
我在这里写了博客:http://blog.onideas.ws/eratosthenes.go
该程序可以在大约10秒钟内筛选出第一批百万个素数(所有素数达到15,485,863).筛子是并发的,但算法主要是同步的:goroutines("actor" - 如果你愿意)之间需要太多同步点,因此它们不能并行自由漫游.
小智 3
“badarity”错误意味着您尝试使用错误数量的参数调用“fun”。在这种情况下...
%%L = for(1,N, fun() -> 产卵(fun(I) -> 等待(I,N) 结束) 结束),
for/3 函数期望 arity 1 的 fun,spawn/1 函数期望 arity 0 的 fun。请尝试以下操作:
L = for(1, N, fun(I) -> spawn(fun() -> wait(I, N) end) end),
Run Code Online (Sandbox Code Playgroud)
传递给spawn的乐趣继承了其环境的所需部分(即I),因此无需显式传递它。
虽然计算素数总是很有趣,但请记住,这不是 Erlang 旨在解决的问题。Erlang 是为大规模 Actor 式并发而设计的。它很可能在所有数据并行计算的例子上表现得相当糟糕。在许多情况下,ML 中的顺序解决方案速度非常快,任何数量的内核都不足以让 Erlang 赶上,例如F# 和 .NET 任务并行库肯定是此类解决方案的更好工具的操作。