我正在尝试在Erlang中创建一个多线程(?)程序:
到目前为止,我认为我已经完成了前三个...我无法弄清楚如何通过在每次插入时打印出每个键 - 哈希对来测试我的树。
主线程:
-module(lineread).
-export([read/1]).
read(Wordlength) ->
{ok, Input} = file:open("/home/ml/datasets/tweets/first60kTweets.txt", [read]),
Threads = makeThreads(Wordlength),
read_lines(Input, Threads).
read_lines(Input, Threads) ->
case file:read_line(Input) of
eof ->
file:close(Input);
{ok, Line} ->
send_to_all(Threads, Line),
read_lines(Input, Threads)
end.
send_to_all(Threads, Line) ->
lists:foreach(fun(Pid) ->
Pid ! {line, Line} end,
Threads).
makeThreads(NumThreads) ->
[ spawn(counter, run, [N]) || N <- lists:seq(1, NumThreads) ].
其他主题:
-module(counter).
-export([run/1]).
%%entry point for the code
run(K) ->
loop(K, gb_trees:empty()).
%%loops for a recieved message
loop(Size, Tree) ->
receive
{line, Line} ->
%%io:format("~p~n", [Line]),
Splits = re:split(Line, " "),
NewTree = build_tree(Splits, Tree),
loop(Size, NewTree);
{char, Char} ->
io:format("~p", [Char])
%%loop(Size, )
end.
%%puts the data into a Tree...
build_tree([], Tree) ->
Tree;
build_tree([W|R], Tree) ->
case gb_trees:is_defined(W, Tree) of
true ->
I = gb_trees:get(W, Tree),
NewTree = gb_trees:update(W, I + 1, Tree),
io:format(I),
build_tree(R, NewTree);
false ->
NewTree = gb_trees:insert(W, 1, Tree),
%%io:format("~p/~n"),
build_tree(R, NewTree)
end.
感谢您的帮助。
答案 0 :(得分:1)
我发现您的程序存在很多问题,但要回答您的问题,您需要了解如何使用receive
来让您的流程相互通信。我建议您阅读前几章here - 特别是this one。话虽如此,这是我对代码的评论:
Size
从未使用过所有进程都是相同的。答案 1 :(得分:0)
我不知道如果我完全关注,我想你正试图让字数统计。
您可以在循环中添加一条看起来像
的新消息{print} - &gt; io:format(“〜p~n”,gb_trees:to_list(Tree)), io:format(“Words~p~n”,gb_trees:size(Tree)), loop(Size,NewTree);
另外我不明白为什么你把每一行发送到所有进程..这只是为了练习?或试图建立一些可以快速计算单词的东西?这不会。
我很少暗示: 您还可以使用stringtokens来分割单词。 http://www.erlang.org/doc/man/string.html
我会使用单词process而不是thread,因为Erlang声称它会创建轻量级进程而不是线程 http://www.erlang.org/doc/efficiency_guide/processes.html
答案 2 :(得分:0)
最大的问题是这项练习的目的是什么?它是真正的工作还是只是某种学习。如果它应该是真正的产品你不能很好地开始。你应该首先询问这些数据的来源,然后你应该尝试确定瓶颈的位置。在你的情况下,你说的是600MB。保存在内存中的数据并不多。如果你必须从某个存储中读取它,你的解决方案将强烈依赖于这个存储,因为从CPU的角度来看,如果你期望平均字大小为10B,则600MB字可以是大约60M字,如果你期望平均6B字,则可以是100M字。你有多快可以计算100M字?如果您使用基于某些东西的k / v解决方案,您可以在一个商用CPU核心上以1s的速度完成。听起来很疯狂?不,它比第一眼看上去容易。如果您的解决方案基于Judy Array或您自己手工制作的实现,您可以相对轻松地获得这样的结果,如果您不是通过C编码吓到的话。那么您可以多快地从数据存储中获取这个野兽?如果您使用商品磁盘,您可以在6s内读取数据!如果你更好地调整它,你可以做得更好但是在相同的时间内完成处理将是挑战。你为什么试着让它平行?只有当您必须真正从存储中读取数据时,才会出现这种情况。例如,当您正在阅读之前由某个流程存储的数据时,情况并非如此。在这种情况下,您可以更快地访问此数据,因为它将在高概率的缓存中。在这种情况下,它将以非常不同的方式表现。例如,您可以随机访问数据。以上阅读时间只能通过从传统磁盘顺序读取来实现。 SSD表现不同,但整体数据吞吐量不是更好。因此,只有你能够足够快地充满你的CPU工作,那么你的并行性努力是值得的。那么最大的问题将是如何放弃数据并对其进行分区。如需灵感,请查看Tim Bray's Wide Finder Project。但请记住,首先使用刷新的IO缓存来测量Wide Finder项目,因此可以从缓存中随机访问数据。即使在这种情况下你也可以使用Erlang,但不要忘记它的一个优点就是与其他语言接口,特别是C和我会指向NIF。
如果目的只在Erlang练习,我的问题是为什么树?为什么不ets:update_counter/3?如果您认为ets不够快,请尝试处理字典而不是gb_trees。在您自己控制的过程中使用它时,它不会那么脏。考虑在memmory中读取整个文件但使用二进制文件。密集使用binary模块,所以......