并发主发电机 [英] Concurrent Prime Generator

查看:156
本文介绍了并发主发电机的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过projecteuler.net上的问题学习如何在Erlang中编程,我最难以创建一个初级生成器,可以在不到一分钟内创建所有的低于200万的素数。使用顺序风格,我已经写了三种类型的发电机,包括筛子的Eratosthenes,并没有一个表现得很好。



我想同时Sieve将工作伟大,但我得到bad_arity消息,我不知道为什么。任何建议为什么我有这个问题,或如何正确地编码?



这里是我的代码,注释掉的部分是我试图使事情并发:

 
-module(primeserver)。
-compile(export_all)。

start() - >
注册(primes,spawn(fun() - > loop()end))。

is_prime(N) - > rpc({is_prime,N})。

rpc(请求) - >
primes! {self(),Request},
接收
{primes,Response} - >
响应
end。

loop() - >
receive
{From,{is_prime,N}} - >
如果
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)),
从! {primes,Val}
end,
loop()
end。

for(N,N,_,F) - > [F(N)];当I + S [F(I)| for(I + S,N,S,F)]时,对于(I,N,S,F)的
;当I + S =:= N→[F(I)| for(I + S,N,S,F)]时,
表示(I,N,S,F)当I + S> N→[F(I)]时,对于(I,N,S,F)


get_list(I,Limit) - >
如果
I
[I * A || A
[]
end。

is_not_prime(N) - >
for(3,N,2,
fun(I) - >
List = get_list I)),
列表:member(N,lists:flatten(List))
end
)。

%% L = for(1,N,fun() - > spawn(fun(I) - > wait(I,N)end),
%% SeedList = [A || A
%% lists:foreach(fun(X) - >
%% Pid!{in_list,X}
%% end,SeedList)
%% end, 。

%% wait(I,N) - >
%% List = [I * A || A lists:member(X,List)
%% end。


解决方案

'badarity'错误意味着你试图调用'fun'参数的数量错误。在这种情况下...



%% L = for(1,N,fun() end)end),



for / 3函数期望有一个arity 1的乐趣,spawn / 1函数期待arity 0的乐趣。 / p>

  L = for(1,N,fun(I) N)end)end),



传递给spawn的乐趣继承其环境的所需部分),所以没有必要明确传递它。



计算素数总是很有趣,请记住这不是Erlang设计的那种问题解决。 Erlang是为大规模的actor风格的并发而设计的。它很可能在数据并行计算的所有示例上执行得相当糟糕。在许多情况下,一个顺序解决方案,例如ML 将会很快,任何数量的核都不足以让Erlang赶上,例如 F#和.NET任务并行库肯定会是这些类型的操作更好的工具。


I'm going through the problems on projecteuler.net to learn how to program in Erlang, and I am having the hardest time creating a prime generator that can create all of the primes below 2 million, in less than a minute. Using the sequential style, I have already written three types of generators, including the Sieve of Eratosthenes, and none of them perform well enough.

I figured a concurrent Sieve would work great, but I'm getting bad_arity messages, and I'm not sure why. Any suggestions on why I have the problem, or how to code it properly?

Here's my code, the commented out sections are where I tried to make things concurrent:

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

解决方案

The 'badarity' error means that you're trying to call a 'fun' with the wrong number of arguments. In this case...

%%L = for(1,N, fun() -> spawn(fun(I) -> wait(I,N) end) end),

The for/3 function expects a fun of arity 1, and the spawn/1 function expects a fun of arity 0. Try this instead:

L = for(1, N, fun(I) -> spawn(fun() -> wait(I, N) end) end),

The fun passed to spawn inherits needed parts of its environment (namely I), so there's no need to pass it explicitly.

While calculating primes is always good fun, please keep in mind that this is not the kind of problem Erlang was designed to solve. Erlang was designed for massive actor-style concurrency. It will most likely perform rather badly on all examples of data-parallel computation. In many cases, a sequential solution in, say, ML will be so fast that any number of cores will not suffice for Erlang to catch up, and e.g. F# and the .NET Task Parallel Library would certainly be a much better vehicle for these kinds of operations.

这篇关于并发主发电机的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆