-module(test).
%%-export([sum_primes/1]).
-compile(export_all).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%Sum of all primes below Max. Will use sieve of Eratosthenes
sum_primes(Max) ->
LastCheck = round(math:sqrt(Max)),
All = lists:seq(3, Max, 2), %note are creating odd-only array
%%Primes = sieve(noref,All, LastCheck),
Primes = spawn_sieve(All, LastCheck),
lists:sum(Primes) + 2. %adding back the number 2 to the list
%%sieve of Eratosthenes
sieve(Ref,All, LastCheck) ->
sieve(Ref,[], All, LastCheck).
sieve(noref,Primes, All = [Cur|_], LastCheck) when Cur > LastCheck ->
lists:reverse(Primes, All); %all known primes and all remaining from list (not sieved) are prime
sieve({Pid,Ref},Primes, All=[Cur|_], LastCheck) when Cur > LastCheck ->
Pid ! {Ref,lists:reverse(Primes, All)};
sieve(Ref,Primes, [Cur|All2], LastCheck) ->
%%All3 = lists:filter(fun(X) -> X rem Cur =/= 0 end, All2),
All3 = lists_filter(Cur,All2),
sieve(Ref,[Cur|Primes], All3, LastCheck).
lists_filter(Cur,All2) ->
lists_filter(Cur,All2,[]).
lists_filter(V,[H|T],L) ->
case H rem V of
0 ->
lists_filter(V,T,L);
_ ->
lists_filter(V,T,[H|L])
end;
lists_filter(_,[],L) ->
lists:reverse(L).
%% This is a sloppy implementation ;)
spawn_sieve(All,Last) ->
%% split the job
{L1,L2} = lists:split(round(length(All)/2),All),
Filters = filters(All,Last),
L3 = lists:append(Filters,L2),
Pid = self(),
Ref1=make_ref(),
Ref2=make_ref(),
erlang:spawn(?MODULE,sieve,[{Pid,Ref1},L1,Last]),
erlang:spawn(?MODULE,sieve,[{Pid,Ref2},L3,Last]),
Res1=receive
{Ref1,R1} ->
{1,R1};
{Ref2,R1} ->
{2,R1}
end,
Res2= receive
{Ref1,R2} ->
{1,R2};
{Ref2,R2} ->
{2,R2}
end,
apnd(Filters,Res1,Res2).
filters([H|T],Last) when H
[H|filters(T,Last)];
filters([H|_],_) ->
[H];
filters(_,_) ->
[].
apnd(Filters,{1,N1},{2,N2}) ->
lists:append(N1,subtract(N2,Filters));
apnd(Filters,{2,N2},{1,N1}) ->
lists:append(N1,subtract(N2,Filters)).
subtract([H|L],[H|T]) ->
subtract(L,T);
subtract(L=[A|_],[B|_]) when A > B ->
L;
subtract(L,[_|T]) ->
subtract(L,T);
subtract(L,[]) ->
L.
My previous post did not get formatted correctly. Here is a repost of the code. Sorry for spamming...
-module(test).
%%-export([sum_primes/1]).
-compile(export_all).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%Sum of all primes below Max. Will use sieve of Eratosthenes
sum_primes(Max) ->
LastCheck = round(math:sqrt(Max)),
All = lists:seq(3, Max, 2), %note are creating odd-only array
%%Primes = sieve(noref,All, LastCheck),
Primes = spawn_sieve(All, LastCheck),
lists:sum(Primes) + 2. %adding back the number 2 to the list
%%sieve of Eratosthenes
sieve(Ref,All, LastCheck) ->
sieve(Ref,[], All, LastCheck).
sieve(noref,Primes, All = [Cur|_], LastCheck) when Cur > LastCheck ->
lists:reverse(Primes, All); %all known primes and all remaining from list (not sieved) are prime
sieve({Pid,Ref},Primes, All=[Cur|_], LastCheck) when Cur > LastCheck ->
Pid ! {Ref,lists:reverse(Primes, All)};
sieve(Ref,Primes, [Cur|All2], LastCheck) ->
%%All3 = lists:filter(fun(X) -> X rem Cur =/= 0 end, All2),
All3 = lists_filter(Cur,All2),
sieve(Ref,[Cur|Primes], All3, LastCheck).
lists_filter(Cur,All2) ->
lists_filter(Cur,All2,[]).
lists_filter(V,[H|T],L) ->
case H rem V of
0 ->
lists_filter(V,T,L);
_ ->
lists_filter(V,T,[H|L])
end;
lists_filter(_,[],L) ->
lists:reverse(L).
%% This is a sloppy implementation ;)
spawn_sieve(All,Last) ->
%% split the job
{L1,L2} = lists:split(round(length(All)/2),All),
Filters = filters(All,Last),
L3 = lists:append(Filters,L2),
Pid = self(),
Ref1=make_ref(),
Ref2=make_ref(),
erlang:spawn(?MODULE,sieve,[{Pid,Ref1},L1,Last]),
erlang:spawn(?MODULE,sieve,[{Pid,Ref2},L3,Last]),
Res1=receive
{Ref1,R1} ->
{1,R1};
{Ref2,R1} ->
{2,R1}
end,
Res2= receive
{Ref1,R2} ->
{1,R2};
{Ref2,R2} ->
{2,R2}
end,
apnd(Filters,Res1,Res2).
filters([H|T],Last) when H
[H|filters(T,Last)];
filters([H|_],_) ->
[H];
filters(_,_) ->
[].
apnd(Filters,{1,N1},{2,N2}) ->
lists:append(N1,subtract(N2,Filters));
apnd(Filters,{2,N2},{1,N1}) ->
lists:append(N1,subtract(N2,Filters)).
subtract([H|L],[H|T]) ->
subtract(L,T);
subtract(L=[A|_],[B|_]) when A > B ->
L;
subtract(L,[_|T]) ->
subtract(L,T);
subtract(L,[]) ->
L.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Sum of all primes below Max. Will use sieve of Eratosthenes
sum_primes(Max) ->
LastCheck = round(math:sqrt(Max)),
All = lists:seq(3, Max, 2), %note are creating odd-only array
Primes = sieve(All, Max, LastCheck),
%io:format("Primes: ~p~n", [Primes]),
lists:sum(Primes) + 2. %adding back the number 2 to the list
%sieve of Eratosthenes
sieve(All, Max, LastCheck) ->
sieve([], All, Max, LastCheck).
sieve(Primes, All, Max, LastCheck) ->
%swap the first element of All onto Primes
[Cur|All2] = All,
Primes2 = [Cur|Primes],
case Cur > LastCheck of
true ->
lists:append(Primes2, All2); %all known primes and all remaining from list (not sieved) are prime
false ->
All3 = lists:filter(fun(X) -> X rem Cur =/= 0 end, All2),
sieve(Primes2, All3, Max, LastCheck)
end.
I haven't studied these in detail, but I've tested my implementation below (that I wrote for a Project Euler challenge) and it's orders of magnitude faster than the above two implementations. It was excruciatingly slow until I eliminated some custom functions and instead looked for lists: functions that would do the same. It's good to learn the lesson to always see if there's a library implementation of something you need to do - it'll usually be faster! This calculates the sum of primes up to 2 million in 3.6 seconds on a 2.8GHz iMac...
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Sum of all primes below Max. Will use sieve of Eratosthenes
sum_primes(Max) ->
LastCheck = round(math:sqrt(Max)),
All = lists:seq(3, Max, 2), %note are creating odd-only array
Primes = sieve(All, Max, LastCheck),
%io:format("Primes: ~p~n", [Primes]),
lists:sum(Primes) + 2. %adding back the number 2 to the list
%sieve of Eratosthenes
sieve(All, Max, LastCheck) ->
sieve([], All, Max, LastCheck).
sieve(Primes, All, Max, LastCheck) ->
%swap the first element of All onto Primes
[Cur|All2] = All,
Primes2 = [Cur|Primes],
case Cur > LastCheck of
true ->
lists:append(Primes2, All2); %all known primes and all remaining from list (not sieved) are prime
false ->
All3 = lists:filter(fun(X) -> X rem Cur =/= 0 end, All2),
sieve(Primes2, All3, Max, LastCheck)
end.
-module(test).
%%-export([sum_primes/1]).
-compile(export_all).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%Sum of all primes below Max. Will use sieve of Eratosthenes
sum_primes(Max) ->
LastCheck = round(math:sqrt(Max)),
All = lists:seq(3, Max, 2), %note are creating odd-only array
%%Primes = sieve(noref,All, LastCheck),
Primes = spawn_sieve(All, LastCheck),
lists:sum(Primes) + 2. %adding back the number 2 to the list
%%sieve of Eratosthenes
sieve(Ref,All, LastCheck) ->
sieve(Ref,[], All, LastCheck).
sieve(noref,Primes, All = [Cur|_], LastCheck) when Cur > LastCheck ->
lists:reverse(Primes, All); %all known primes and all remaining from list (not sieved) are prime
sieve({Pid,Ref},Primes, All=[Cur|_], LastCheck) when Cur > LastCheck ->
Pid ! {Ref,lists:reverse(Primes, All)};
sieve(Ref,Primes, [Cur|All2], LastCheck) ->
%%All3 = lists:filter(fun(X) -> X rem Cur =/= 0 end, All2),
All3 = lists_filter(Cur,All2),
sieve(Ref,[Cur|Primes], All3, LastCheck).
lists_filter(Cur,All2) ->
lists_filter(Cur,All2,[]).
lists_filter(V,[H|T],L) ->
case H rem V of
0 ->
lists_filter(V,T,L);
_ ->
lists_filter(V,T,[H|L])
end;
lists_filter(_,[],L) ->
lists:reverse(L).
%% This is a sloppy implementation ;)
spawn_sieve(All,Last) ->
%% split the job
{L1,L2} = lists:split(round(length(All)/2),All),
Filters = filters(All,Last),
%%io:format("F:~p~n",[Filters]),
L3 = lists:append(Filters,L2),
%%io:format("L1:~w~n",[L1]),
%% io:format("L2:~w~n",[L3]),
%%lists_filter(Cur,All2,[]).
Pid = self(),
Ref1=make_ref(),
Ref2=make_ref(),
erlang:spawn(?MODULE,sieve,[{Pid,Ref1},L1,Last]),
erlang:spawn(?MODULE,sieve,[{Pid,Ref2},L3,Last]),
Res1=receive
{Ref1,R1} ->
{1,R1};
{Ref2,R1} ->
{2,R1}
end,
Res2= receive
{Ref1,R2} ->
{1,R2};
{Ref2,R2} ->
{2,R2}
end,
apnd(Filters,Res1,Res2).
filters([H|T],Last) when H
[H|filters(T,Last)];
filters([H|_],_) ->
[H];
filters(_,_) ->
[].
apnd(Filters,{1,N1},{2,N2}) ->
lists:append(N1,subtract(N2,Filters));
apnd(Filters,{2,N2},{1,N1}) ->
lists:append(N1,subtract(N2,Filters)).
subtract([H|L],[H|T]) ->
subtract(L,T);
subtract(L=[A|_],[B|_]) when A > B ->
L;
subtract(L,[_|T]) ->
subtract(L,T);
subtract(L,[]) ->
L.
I kind of like this subject, primes that is, so I started to modify BarryE's code a bit and I manged to make it about 70% faster by making my own lists_filter function and made it possible to utilize both of my CPUs. I also made it easy to swap between to two version. A test run shows:
-module(test).
%%-export([sum_primes/1]).
-compile(export_all).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%Sum of all primes below Max. Will use sieve of Eratosthenes
sum_primes(Max) ->
LastCheck = round(math:sqrt(Max)),
All = lists:seq(3, Max, 2), %note are creating odd-only array
%%Primes = sieve(noref,All, LastCheck),
Primes = spawn_sieve(All, LastCheck),
lists:sum(Primes) + 2. %adding back the number 2 to the list
%%sieve of Eratosthenes
sieve(Ref,All, LastCheck) ->
sieve(Ref,[], All, LastCheck).
sieve(noref,Primes, All = [Cur|_], LastCheck) when Cur > LastCheck ->
lists:reverse(Primes, All); %all known primes and all remaining from list (not sieved) are prime
sieve({Pid,Ref},Primes, All=[Cur|_], LastCheck) when Cur > LastCheck ->
Pid ! {Ref,lists:reverse(Primes, All)};
sieve(Ref,Primes, [Cur|All2], LastCheck) ->
%%All3 = lists:filter(fun(X) -> X rem Cur =/= 0 end, All2),
All3 = lists_filter(Cur,All2),
sieve(Ref,[Cur|Primes], All3, LastCheck).
lists_filter(Cur,All2) ->
lists_filter(Cur,All2,[]).
lists_filter(V,[H|T],L) ->
case H rem V of
0 ->
lists_filter(V,T,L);
_ ->
lists_filter(V,T,[H|L])
end;
lists_filter(_,[],L) ->
lists:reverse(L).
%% This is a sloppy implementation ;)
spawn_sieve(All,Last) ->
%% split the job
{L1,L2} = lists:split(round(length(All)/2),All),
Filters = filters(All,Last),
%%io:format("F:~p~n",[Filters]),
L3 = lists:append(Filters,L2),
%%io:format("L1:~w~n",[L1]),
%% io:format("L2:~w~n",[L3]),
%%lists_filter(Cur,All2,[]).
Pid = self(),
Ref1=make_ref(),
Ref2=make_ref(),
erlang:spawn(?MODULE,sieve,[{Pid,Ref1},L1,Last]),
erlang:spawn(?MODULE,sieve,[{Pid,Ref2},L3,Last]),
Res1=receive
{Ref1,R1} ->
{1,R1};
{Ref2,R1} ->
{2,R1}
end,
Res2= receive
{Ref1,R2} ->
{1,R2};
{Ref2,R2} ->
{2,R2}
end,
apnd(Filters,Res1,Res2).
filters([H|T],Last) when H
[H|filters(T,Last)];
filters([H|_],_) ->
[H];
filters(_,_) ->
[].
apnd(Filters,{1,N1},{2,N2}) ->
lists:append(N1,subtract(N2,Filters));
apnd(Filters,{2,N2},{1,N1}) ->
lists:append(N1,subtract(N2,Filters)).
subtract([H|L],[H|T]) ->
subtract(L,T);
subtract(L=[A|_],[B|_]) when A > B ->
L;
subtract(L,[_|T]) ->
subtract(L,T);
subtract(L,[]) ->
L.
-nonstop operation, new code can be loaded on the fly.
-easy to debug, no more core dumps to analyse.
-easy to utilize multi core/CPUs
-easy to utilize clusters maybe?
-who wants to deal with pointers and stuff? Is this not the 21 century? ;)
Some pifalls: - it might look easy and fast to write something, but the performance can suck. If I want to make something fast I usually end up writing 2-4 different versions of the same function. And often you need to take a hawk eye aproach to problems which might be a little bit different from what one is used too.
looking up things in lists > about 1000 elements is slow, try using ets tables.
the string "abc" takes a lot more space than 3 bytes. So try to use binaries, (which is a pain).
All in all i think the performance issue is something to keep in mind at all times when writing something in erlang. The Erlang dudes need to work that out, and I think they will.
Have a look here to find 4 different implementations for finding prime numbers in Erlang (two of which are "real" sieves) and for performance measurement results:
Simple enough, implements exactly the algorithm, and uses no library functions (only pattern matching and list comprehension). Not very powerful, indeed. I only tried to make it as simple as possible.
发布评论
评论(12)
这是我的样本
:-)
Here is my sample
:-)
到目前为止,我最快的代码(比 Andrea 的更快)是使用数组:
my fastest code so far (faster than Andrea's) is with using array:
这是一个简单(但不是非常快)的筛子实现:
Here's a simple (but not terribly fast) sieve implementation:
这是我的筛子实现,它使用列表理解并尝试尾递归。 我在最后颠倒了列表,以便对素数进行排序:
在我的 2ghz mac 上计算最多 200 万个素数大约需要 2.8 毫秒。
Here's my sieve implementation which uses list comprehensions and tries to be tail recursive. I reverse the list at the end so the primes are sorted:
Takes approx 2.8 ms to calculate primes up to 2 mil on my 2ghz mac.
我之前的帖子格式不正确。 这是代码的重新发布。 抱歉,乱发垃圾邮件...
My previous post did not get formatted correctly. Here is a repost of the code. Sorry for spamming...
我通过使用并发处理来解决这个问题。
来源
I approached the problem by using concurrent processing.
Source
我没有详细研究这些,但我在下面测试了我的实现(我为欧拉项目挑战编写的),它比上述两个实现快几个数量级。 它非常慢,直到我消除了一些自定义函数并转而寻找列表:可以执行相同操作的函数。 学习这个教训是很好的,总是看看是否有一个库实现了你需要做的事情 - 它通常会更快! 在 2.8GHz iMac 上,这可以在 3.6 秒内计算出最多 200 万个素数之和...
I haven't studied these in detail, but I've tested my implementation below (that I wrote for a Project Euler challenge) and it's orders of magnitude faster than the above two implementations. It was excruciatingly slow until I eliminated some custom functions and instead looked for lists: functions that would do the same. It's good to learn the lesson to always see if there's a library implementation of something you need to do - it'll usually be faster! This calculates the sum of primes up to 2 million in 3.6 seconds on a 2.8GHz iMac...
我有点喜欢这个主题,即素数,所以我开始稍微修改 BarryE 的代码,并通过制作我自己的 Lists_filter 函数,设法使其速度提高了 70% 左右,并且可以利用我的两个 CPU。 我还使两个版本之间的切换变得容易。 测试运行显示:
代码:
I kind of like this subject, primes that is, so I started to modify BarryE's code a bit and I manged to make it about 70% faster by making my own lists_filter function and made it possible to utilize both of my CPUs. I also made it easy to swap between to two version. A test run shows:
Code:
你可以向你的老板展示这个: http://www.sics.se/~joe/apachevsyaws .html。 其他一些(经典?)erlang 参数是:
-不间断操作,可以动态加载新代码。
- 易于调试,不再需要分析核心转储。
- 易于使用多核/CPU
- 易于使用集群吗?
-谁想处理指针之类的东西? 这不是21世纪吗? ;)
一些错误:
- 写东西可能看起来简单快捷,但性能可能很糟糕。 如果我
想要快速制作一些东西,我通常最终会编写相同的 2-4 个不同版本
功能。 通常,您需要以鹰眼的态度来解决可能会出现问题的问题。
与使用的也有点不同。
在列表中查找内容> 大约 1000 个元素很慢,请尝试使用 ets 表。
字符串“abc”占用的空间比 3 个字节多得多。 所以尝试使用二进制文件(这很痛苦)。
总而言之,我认为在用 erlang 编写东西时要始终牢记性能问题。 Erlang 兄弟们需要解决这个问题,我想他们会的。
you could show your boss this: http://www.sics.se/~joe/apachevsyaws.html. And some other (classic?) erlang arguments are:
-nonstop operation, new code can be loaded on the fly.
-easy to debug, no more core dumps to analyse.
-easy to utilize multi core/CPUs
-easy to utilize clusters maybe?
-who wants to deal with pointers and stuff? Is this not the 21 century? ;)
Some pifalls:
- it might look easy and fast to write something, but the performance can suck. If I
want to make something fast I usually end up writing 2-4 different versions of the same
function. And often you need to take a hawk eye aproach to problems which might be a
little bit different from what one is used too.
looking up things in lists > about 1000 elements is slow, try using ets tables.
the string "abc" takes a lot more space than 3 bytes. So try to use binaries, (which is a pain).
All in all i think the performance issue is something to keep in mind at all times when writing something in erlang. The Erlang dudes need to work that out, and I think they will.
在这里查看 4 种不同的实现,用于在 Erlang 中查找素数(其中两个是“真正的”筛子)和性能测量结果:
Have a look here to find 4 different implementations for finding prime numbers in Erlang (two of which are "real" sieves) and for performance measurement results:
足够简单,准确实现算法,并且不使用库函数(仅模式匹配和列表理解)。
确实不是很强大。 我只是试图让它尽可能简单。
Simple enough, implements exactly the algorithm, and uses no library functions (only pattern matching and list comprehension).
Not very powerful, indeed. I only tried to make it as simple as possible.
这是我的eratophenes实施C&C的筛子,请:
Here is my sieve of eratophenes implementation C&C please: