我目前通過網站exercism.io學習Elixir。 我有問題「總和的倍數」是:多進程效率低下
如果我們列出所有的自然數,直到但不包括20是3或5 倍數,我們得到了3,5,6和9,10,12,15,和18 這些倍數的總和是78
我解決了這個問題,此代碼:
defmodule SumOfMultiples do
@doc """
Adds up all numbers from 1 to a given end number that are multiples of the factors provided.
"""
@spec to(non_neg_integer, [non_neg_integer]) :: non_neg_integer
def to(limit, factors) do
1..limit - 1
|> Enum.reduce([], fn(x,acc) ->
is_multiple? = factors
|> Enum.map(&(rem(x,&1) === 0))
|> Enum.any?
if is_multiple?, do: [x|acc], else: acc
end)
|> Enum.sum
end
end
但我最近發現過程中藥劑所以想解決p多進程問題:
defmodule SumOfMultiples do
@doc """
Adds up all numbers from 1 to a given end number that are multiples of the factors provided.
"""
@spec to(non_neg_integer, [non_neg_integer]) :: non_neg_integer
def to(limit, factors) do
me = self
1..limit - 1
|> Enum.map(fn(x) ->
spawn(SumOfMultiples, :is_multiple?, [x, factors, me])
end)
|> Enum.map(fn(_) ->
receive do
{true, n} -> n
{false, n} -> 0
end
end)
|> Enum.sum
end
def is_multiple?(n, factors, pid) do
flag = factors
|> Enum.map(&(rem(n,&1) === 0))
|> Enum.any?
send pid, {flag, n}
end
end
我使用並行映射來解決這個問題。是有效的,但事情是比單進程版本低4倍的性能。
如果有人能解釋我爲什麼會出現這種性能差異,這將是非常有用的,因爲我已計劃用多進程版本解決剩餘的exerciseism.io問題。
謝謝!
---------------------更新---------------------
謝謝你的回答!事實證明你是對的!感謝您的解釋!這裏是我的新實現:
defmodule SumOfMultiples do
@doc """
Adds up all numbers from 1 to a given end number that are multiples of the factors provided.
"""
@spec to(non_neg_integer, [non_neg_integer]) :: non_neg_integer
def to(limit, factors) do
me = self
1..limit - 1
|> Stream.chunk(200, 200, Stream.cycle([0]))
|> Enum.map(fn(x) ->
spawn(SumOfMultiples, :do_to, [x, factors, me])
end)
|> Enum.map(fn(_) ->
receive do
n -> n
end
end)
|> Enum.sum
end
def do_to(list, factors, pid) do
result = list
|> Enum.reduce([], fn(x,acc) ->
is_multiple? = factors
|> Enum.map(&(rem(x,&1) === 0))
|> Enum.any?
if is_multiple?, do: [x|acc], else: acc
end)
|> Enum.sum
send pid, result
end
end
最大似乎是200.現在我比〜單程40%快!好極了 !
Stream.chunk_by()是你的朋友 – GavinBrelstaff