Erlang 二郎字计数器

Erlang 二郎字计数器,erlang,count,word,parallel-processing,Erlang,Count,Word,Parallel Processing,我正试图在Erlang中创建一个多线程(?)程序: 读取大文件(600mb) 向一组已创建的进程激发消息,这些进程包含从文件中读取的行 创建的进程处理单词并存储在哈希树中 创建的进程然后将哈希树激发回主进程 大师打印这棵树 到目前为止,我想我已经完成了前三个。。。我不知道如何通过在每次插入密钥哈希对时打印它们来测试我的树 主线程: -module(lineread). -export([read/1]). read(Wordlength) -> {ok, Input} = fil

我正试图在Erlang中创建一个多线程(?)程序:

  • 读取大文件(600mb)
  • 向一组已创建的进程激发消息,这些进程包含从文件中读取的行
  • 创建的进程处理单词并存储在哈希树中
  • 创建的进程然后将哈希树激发回主进程
  • 大师打印这棵树
  • 到目前为止,我想我已经完成了前三个。。。我不知道如何通过在每次插入密钥哈希对时打印它们来测试我的树

    主线程:

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

    谢谢你的帮助。

    我不知道,如果我完全听懂了,我想你是在努力统计字数

    您可以向循环中添加一条新消息,如下所示

    {print}-> io:格式(“~p~n”,gb_树:to_列表(树)), io:format(“Words~p~n”,gb_trees:size(Tree)), 循环(大小,新树)

    我也不明白为什么你要把每一行都发送给所有的进程。。这只是为了练习?或者尝试建立一个可以快速数词的东西?这是不可能的

    我有几点建议: 您还可以使用StringToken分割单词。

    我会使用进程这个词而不是线程,因为Erlang声称它创建的是轻量级进程而不是线程

    我不知道,如果我完全听懂了,我想你是想知道字数

    您可以向循环中添加一条新消息,如下所示

    {print}-> io:格式(“~p~n”,gb_树:to_列表(树)), io:format(“Words~p~n”,gb_trees:size(Tree)), 循环(大小,新树)

    我也不明白为什么你要把每一行都发送给所有的进程。。这只是为了练习?或者尝试建立一个可以快速数词的东西?这是不可能的

    我有几点建议: 您还可以使用StringToken分割单词。

    我会使用进程这个词而不是线程,因为Erlang声称它创建的是轻量级进程而不是线程
    最大的问题是这个练习的目的是什么?是为了真正的工作还是仅仅为了某种学习。如果它应该是真正的产品,你就不能很好地开始它。你们的第一个问题应该是这些数据从哪里来,然后你们应该试着找出哪里是瓶颈。在您的情况下,您所说的是600MB。存储在内存中的数据并不多。如果您必须从某个存储中读取,您的解决方案将强烈依赖于该存储,因为从CPU的角度来看,如果您预期平均字大小为10B,600MB的字可能约为60MB;如果您预期平均字大小为6B,则600MB的字可能约为100MB。你数词的速度有多快?如果您使用基于某个非常快的东西的k/v解决方案,您可以在一个商品CPU内核上以1秒的时间完成。听起来很疯狂?不,这比乍一看容易。如果您的解决方案基于类似的东西或您自己手工制作的trie实现,如果您不害怕用C编写代码,您就可以相对容易地实现这样的结果。那么,您能以多快的速度从数据存储中消化掉这头怪兽呢?如果您使用商品磁盘,您可以在6秒内读取数据!若你们调整得更好,你们可以做得更好,但在和处理时间相当的时间内完成它将是一个挑战。你为什么要让它平行?只有当您必须真正从存储器中读取数据时,以上才是正确的。例如,当您正在读取之前某个进程存储的数据时,情况并非如此。在这种情况下,您可以更快地访问此数据,因为它很可能位于缓存中。在这种情况下,它将以完全不同的方式运行。例如,您可以随机访问数据。上述读取定时只能通过从经典磁盘顺序读取来实现。SSD的表现有所不同,但总体数据吞吐量并没有达到更好的数量级。因此,只有当您能够足够快地完成CPU工作时,并行化的努力才是值得的。然后最大的问题将是如何填充数据并对其进行分区。你可以从中获得灵感。但请记住,第一个WideFinder项目并不是用刷新的IO缓存来衡量的,所以数据可以从缓存中随机访问。即使在这种情况下,您也可以使用Erlang,但不要忘记它的优势之一是与其他语言的接口,特别是C语言,我将向您介绍NIFs


    如果目的只是在二郎练习,我的问题是为什么是树?为什么不呢?如果你认为ETS速度不够快,那么尝试使用进程字典代替GBBREST。当你们在自己的控制下使用它的时候,它并没有那个么脏。考虑在内存中读取整个文件,但用二进制工作。集中使用模块,所以…

    最大的问题是这个练习的目的是什么?是为了真正的工作还是仅仅为了某种学习。如果它应该是真正的产品,你就不能很好地开始它。你们的第一个问题应该是这些数据从哪里来,然后你们应该试着找出哪里是瓶颈。在您的情况下,您所说的是600MB。存储在内存中的数据并不多。如果您必须从某个存储中读取,您的解决方案将强烈依赖于该存储,因为从CPU的角度来看,如果您预期平均字大小为10B,600MB的字可能约为60MB;如果您预期平均字大小为6B,则600MB的字可能约为100MB。你数词的速度有多快?如果您使用基于某个非常快的东西的k/v解决方案,您可以在一个商品CPU内核上以1秒的时间完成。听起来很疯狂?不,这比乍一看容易。如果您的解决方案基于类似的东西或您自己手工制作的trie实现,如果您不害怕用C编写代码,您就可以相对容易地实现这样的结果。那么,您能以多快的速度从数据存储中消化掉这头怪兽呢?如果您使用商品磁盘,您可以在6秒内读取数据!若你们调整得更好,你们可以做得更好,但在和处理时间相当的时间内完成它将是一个挑战。你为什么要让它平行?只有当您必须真正从存储器中读取数据时,以上才是正确的。例如,当您正在读取之前某个进程存储的数据时,情况并非如此。在这种情况下,您可以使用c