Does the "Async.Parallel" construction really help to make calculations faster on a multi-core system? Are .NET TPL "Tasks" involved here somehow?
open System;
let key = Console.ReadKey(true);
let start = System.DateTime.Now
let pmap f l = seq { for a in l do yield async {return f a} } |> Async.Parallel |> Async.RunSynchronously
let map f l = seq {for a in l do yield f a}
let work f l =
match key.KeyChar with
| '1' -> pmap f l
| '2' -> Seq.toArray (map f l)
| _ -> [||]
let result = work (fun x -> (x * x) / 75) (seq { 1 .. 100000*3})
let endtime = DateTime.Now - start
printfn "%A"endtime;
let pause = Console.ReadKey(true);
I suppose some of you will explain it theoretically, but I would also appreciate some real world tests.
An overview: What is Y=f(x)? It is one to use when examining different possible outcomes based on the inputs and factors used. The “Y” stands for the outcome, the “f” embodies the function used in the calculation, and the “X” represents the input or inputs used for the formula.
Derivative as a function Let f be a function that has a derivative at every point in its domain. We can then define a function that maps every point x to the value of the derivative of f at x. This function is written f′ and is called the derivative function or the derivative of f.
The function f ´( x ), which would be read `` f -prime of x '', means the derivative of f ( x ) with respect to x . If we say y = f ( x ), then y ´ (read `` y -prime'') = f ´( x ).
To our common sense, when f is always greater than o, then the function is always above x-axis, and when f is always less than 0, f is always below the x-axis. And if f is just greater than 0 at certain range, then it is just above x-axis at that corresponding range, vise versa.
Using F# async
for purely CPU-bound tasks works only if the tasks perform some more complicated operation. If you're trying to parallelize code that does something very simple, then it is better to use PLINQ (and the Task Parallel Library), which are more optimized for these kind of problems.
However, even then, getting speedup in a trivial case as the one you have is difficult. If you want to experiment with this a bit more, you can try this:
// Turn on timing in F# interactive
#time
let data = [| 1 .. 5000000*3 |]
// Use standard 'map' function for arrays
let result = Array.map (fun x -> (x * x) / 75) data
// Use optimized parallel version
let result = Array.Parallel.map (fun x -> (x * x) / 75) data
Note that using Array.map
itself is a lot faster than using sequence expressions and then converting the result to an array. If you want to use more complex operations than mapping, then F# PowerPack contains PSeq
module with functions similar to those in Seq
or List
:
#r @"FSharp.PowerPack.Parallel.Seq.dll"
data
|> PSeq.map (fun a -> ...)
|> PSeq.filter (fun a -> ...)
|> PSeq.sort
|> Array.ofSeq
If you want to read more about this, I wrote a blog series about parallel programming in F# recently.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With