1
我正在玩並行編程和F#。我創建,集成有1可變功能的功能,然後我試圖使它平行於兩種不同的方式:並行代碼與Task.Factory比線性慢
module Quadrature =
let Integrate (f: double -> double) (x1: double) (x2: double) (samples: int64) =
let step = (x2 - x1)/(double samples)
let samplePoints = seq {x1 + step .. step .. x2 - step}
let sum = samplePoints |> Seq.map (fun x -> f x) |> Seq.sum
let sum = sum + ((f x1) + (f x2))/2.0
step * sum
let IntegrateWithStep (f: double -> double) (x1: double) (x2: double) (step: double) =
let samples = (x2 - x1)/step |> round |> int64
Integrate f x1 x2 samples
let IntegrateWithTasks (f: double -> double) (x1: double) (x2: double) (samples: int64) (tasks: int) =
let step = (x2 - x1)/(double samples)
let samplesPerTask = ceil <| (double samples)/(double tasks)
let interval = step * samplesPerTask
let intervals =
seq {
for i in 0 .. (tasks - 1) do
let lowerBound = x1 + (double i) * interval
let upperBound = min (lowerBound + interval) x2
yield (lowerBound, upperBound)
}
let tasks = intervals
|> Seq.map (fun (a, b) -> Task.Factory.StartNew(fun() -> IntegrateWithStep f a b step))
tasks |> Seq.map (fun t -> t.Result) |> Seq.sum
let IntegrateParallel (f: double -> double) (x1: double) (x2: double) (samples: int64) (tasks: int) =
let step = (x2 - x1)/(double samples)
let samplesPerTask = ceil <| (double samples)/(double tasks)
let interval = step * samplesPerTask
let intervals =
[| for i in 0 .. (tasks - 1) do
let lowerBound = x1 + (double i) * interval
let upperBound = min (lowerBound + interval) x2
yield (lowerBound, upperBound) |]
intervals |> Array.Parallel.map (fun (a, b) -> IntegrateWithStep f a b step)
|> Array.sum
運行此代碼與機器上的以下輸入與4芯:
let f = (fun x -> - 1.0 + 2.0 * x - 3.0 * x * x + 4.0 * x * x * x)
let x1, x2 = 0.0, 1.0
let samples = 100000000L
let tasks = 100
但是,使用任務工廠的方法總是比線性方法稍慢,而使用Parallel.map的方法則使我加快了速度。
我曾嘗試改變從數千下降到核心數量的任務數量,但與Task.Factory的實現總是比線性的慢。我究竟做錯了什麼?
我修改了這一行'任務|> Seq.toArray |> Array.map(樂趣筆 - >。 t.Result)|> Array.sum',它現在給我加快了速度,謝謝! – Panos 2012-04-14 08:58:56