Ich spiele mit paralleler Programmierung und F #. Ich habe eine Funktion, die eine 1-variable-Funktion integriert, und dann habe ich versucht, um es auf zwei verschiedene Arten zu machen Parallel:Paralleler Code mit Task.Factory langsamer als linear
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
ich diesen Code mit der folgenden Eingabe mit 4 Kernen auf einer Maschine ausgeführt werden:
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
Allerdings ist die Methode mit der Task Factory immer etwas langsamer als die lineare, während die mit der Parallel.map mir eine gute Geschwindigkeit gibt.
Ich habe versucht, die Anzahl der Aufgaben von Tausenden auf die Anzahl der Kerne zu variieren, aber die Implementierung mit der Task.Factory ist immer langsamer als die lineare. Was mache ich falsch?
ich diese Zeile geändert 'Aufgaben |> Seq.toArray |> Array.map (fun t ->. t.Result) || Array.sum' und es gibt mir jetzt eine Beschleunigung. Danke! – Panos