Parallel processing Erlang进程消息接收

Parallel processing Erlang进程消息接收,parallel-processing,erlang,Parallel Processing,Erlang,我正在与Erlang进行并行计算培训。我有以下代码,用于计算pi数: start(To)-> Self = self(), Cores = erlang:system_info(schedulers_online), {Step, Delta} = {1/To, round(To / Cores)}, Pids = lists:map(fun (El) -> spawn(fun()-> Self ! {su

我正在与Erlang进行并行计算培训。我有以下代码,用于计算pi数:

start(To)->
    Self = self(),
    Cores = erlang:system_info(schedulers_online),
    {Step, Delta} = {1/To, round(To / Cores)},
    Pids = lists:map(fun (El) ->
        spawn(fun()->
            Self ! {sum, calculate(from(El, Delta), to(El, Delta), Step)}
        end)
    end, lists:seq(1, Cores)),
    lists:sum([receive {sum, S} -> S end || _ <- Pids ]) * Step.
现在,它对我来说变魔术了

lists:sum([receive {sum, S} -> S end || _ <- Pids ])
请解释一下这个魔法是怎么起作用的

lists:sum([receive {sum, S} -> S end || _ <- Pids ])
列表:sumSomeList*步骤。将只在SomeList的元素和步骤中的值之间进行乘法

有趣的部分是如何构建列表,这是由代码构建的:

[receive {sum, S} -> S end || _ <- Pids ]
假设你有4个核心,这个函数将创建4个进程,可能有一个类似[,]的列表,主要的重要思想是,如果你有4个核心,你将创建4个进程,如果你有8个核心,8个进程,等等

每个进程都将调用函数calculate,并将结果作为消息发送给Self,您可以在此处看到:

Self ! {sum, calculate(from(El, Delta), to(El, Delta), Step)}
因此,如果您有4个元素,您可以尝试执行以下操作:

6> [X || X <- [1, 2, 3, 4]].
[1,2,3,4]
7> [1 || _ <- [1, 2, 3, 4]].
[1,1,1,1]
[1 || _ <- Pids ]
receive函数将侦听发送到进程的任何消息,模式为{sum,S},这与您使用{sum,calculatefromEl,Delta,toEl,Delta,Step}发送的模式相同。函数的返回值是S,在这种情况下,它将是calculatefromEl,Delta,toEl,Delta,Step的结果

最后,假设您有4个核心,并且结果由您启动的四个进程计算,那么您将再次拥有一个包含4个元素的列表

7> [1 || _ <- [1, 2, 3, 4]].
[1,1,1,1]
[1 || _ <- Pids ]
receive 
    {sum, S} -> 
        S 
end