使用Erlang查找包含K进程的列表中的最大元素?

时间:2011-03-03 02:52:06

标签: erlang

使用单个流程很容易实现算法,但是,如何使用多个流程来完成工作呢?

这是我到目前为止所做的。

 find_largest([H], _) -> H;
 find_largest([H, Q | T], R) ->
     if H > Q -> find_largest([H | T], [Q | R]);
       true -> find_largest([Q | T], [H | R])
 end.

由于

2 个答案:

答案 0 :(得分:5)

考虑到Erlang如何表示列表,尝试并行执行并不是一个好主意。对列表进行分区意味着需要进行大量复制(因为它们是链接列表),并且将这些分区发送到其他进程也是如此。我希望比较比将所有内容复制两次然后合并结果要便宜得多。

实现也不正确,你可以在lists.erl中找到一个好的,作为max / 1

%% max(L) -> returns the maximum element of the list L

-spec max([T,...]) -> T.

max([H|T]) -> max(T, H).

max([H|T], Max) when H > Max -> max(T, H);
max([_|T], Max)              -> max(T, Max);
max([],    Max)              -> Max.

如果您的数据有可能已经在单独的进程中,只需获取列表:max / 1或每个列表并将它们发送到一个地方,然后获取列表:结果列表的max / 1。您也可以在收到结果时进行比较,以避免构建此中间列表。

答案 1 :(得分:2)

代码的单进程版本应替换为lists:max/1。并行化代码的有用功能如下:

pmap(Fun, List) ->
    Parent = self(),
    P = fun(Elem) ->
            Ref = make_ref(),
            spawn_link(fun() -> Parent ! {Ref, Fun(Elem)} end),
            Ref
        end,
    Refs = [P(Elem) || Elem <- List],
    lists:map(fun(Ref) -> receive {Ref, Elem} -> Elem end end, Refs).

pmap/2并行地将Fun应用于List的每个成员,并按输入顺序收集结果。要将pmap用于此问题,您需要将原始列表分段为列表列表并将其传递给pmap。例如lists:max(pmap(fun lists:max/1, ListOfLists))。当然,分割列表的行为比简单地调用lists:max/1更昂贵,因此该解决方案需要预先分段列表。即使这样,复制列表的开销也可能超过并行化的任何好处 - 特别是在单个节点上。

您的情况固有的问题是,与管理数据的开销相比,每个子任务的计算量很小。更加计算密集的任务(例如,将大数据列表分解)更容易并行化。

这并不是说找不到最大值不能并行化,但我相信它需要以不需要迭代每个值的方式对数据进行预分段或分段。