Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does F# Async.Parallel speed up calculations?

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.

like image 395
Anton Andreev Avatar asked Jan 31 '11 14:01

Anton Andreev


People also ask

Does f x mean Y?

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.

Does f mean derivative?

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.

What does f mean in calculus?

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 ).

What does f say about f and f?

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.


1 Answers

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.

like image 119
Tomas Petricek Avatar answered Oct 23 '22 22:10

Tomas Petricek