我手头的任务是读取大文件的行,处理它们,并返回有序的结果。
我的算法是:
我的问题:
答案 0 :(得分:1)
Erlang流程很便宜。您可以自由(并鼓励)使用多于您拥有的核心。可能存在对您的问题的实际上限(每行一个进程中加载1TB数据需要多少时间,具体取决于行大小)。
当您不知道时,最简单的方法是让用户决定。这意味着您可以决定生成N
工作人员,并在他们之间分配工作,等待回复。如果您不喜欢它的运行方式,请在更改N
时重新运行该程序。
更狡猾的方法是对一大堆时间进行基准测试,选择您认为有意义的最大值,将其粘贴在池库中(如果您愿意;某些池用于预分配资源,有些用于可调整大小的资源)数量),并解决什么是一个通用的解决方案。
但实际上,没有简单的'最佳核心数'。如果需要,您可以在50个进程以及65,000个进程上运行它;如果任务是令人尴尬的并行,那么VM应该能够使用它们中的大部分并使核心饱和。
-
并行文件读取是一个有趣的问题。它可能会或可能不会更快(正如直接评论所提到的),如果每行的工作量足够小以至于读取文件的成本最高,它可能仅代表加速。
棘手的一点是pread/2-3
之类的函数需要一个字节偏移量。您的问题是措辞,以至于您担心文件的行。因此,您交给工人的字节偏移可能最终跨越一条线。如果您的广告资源最终位于my
中的this is my line\nhere it goes\n
字词,则一位工作人员会发现自己的行不完整,而另一位工作人员只会报告my line\n
,而错过之前的this is
}。
一般来说,这种烦人的东西会导致你让第一个进程拥有该文件并筛选它,只是将一些文本传递给工人;然后,该过程将充当某种协调者。
这个策略的好处在于,如果主进程知道作为消息发送的所有内容,它还知道何时收到所有响应,从而很容易知道何时返回结果。如果一切都是不相交的,你必须相信首发和工人都要告诉你“我们都失业了”,作为一组独立的独立信息要知道。
在实践中,您可能会发现,最有帮助的是帮助您了解有关文件操作的硬件生命的操作,而不是“有多少人可以一次读取文件”。只有一个硬盘(或SSD),所有数据都必须通过它;并行性最终可能会限制访问那里。
-
使用对您的程序有意义的消息。性能最高的程序将有许多进程能够在不需要传递消息,通信或获取锁的情况下完成工作。
一个更现实的非常高性能的程序将使用非常少的非常小的消息。
这里有趣的是,您的问题本质上是基于数据的。所以你可以做一些事情:
raw
或ram
模式阅读该文件;其他模式使用中间人进程来读取和转发数据(如果您在集群Erlang节点中通过网络读取文件,这将非常有用); raw
和ram
模式将文件描述符直接提供给调用进程,速度更快。我希望这会有所帮助。
P.S。你可以先尝试一下非常简单的东西:
或者:
{ok, Bin} = file:read_file(Path)
和分割线(使用binary:split(Bin, <<"\n">>, [global])
),{ok, Io} = file:open(File, [read,ram])
,然后在文件描述符上重复使用file:read_line(Io)
{ok, Io} = file:open(File, [read,raw,{read_ahead,BlockSize}])
,然后在文件描述符上重复使用file:read_line(Io)
调用rpc:pmap({?MODULE, Function}, ExtraArgs, Lines)
自动并行运行所有内容(每行会生成一个进程)
在结果上调用lists:sort/1
。
然后,如果您将其识别为有问题,则可以从中完善每个步骤。