F # Async.Parallel speed up computing?

Does the Async.Parallel design really speed up computing in a multi-core system? Are the .NET TPL "Tasks" here somehow?

open System; let key = Console.ReadKey(true); let start = System.DateTime.Now let pmap fl = seq { for a in l do yield async {return fa} } |> Async.Parallel |> Async.RunSynchronously let map fl = seq {for a in l do yield fa} let work fl = match key.KeyChar with | '1' -> pmap fl | '2' -> Seq.toArray (map fl) | _ -> [||] 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 believe some of you will explain this theoretically, but I would also like to evaluate some real tests.

+8
parallel-processing f #
source share
3 answers

Using F # async for purely CPU-bound tasks only works if tasks perform a more complex operation. If you are trying to parallelize code that does something very simple, it is best to use PLINQ (and a parallel task library), which are more optimized for these problems.

However, even then, obtaining acceleration in a trivial case, as in your case, is difficult. If you want to experiment a little more with this, you can try the following:

 // 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: using Array.map itself Array.map much faster than using sequence expressions and then converting the result to an array. If you want to use more complex operations than matching, then F # PowerPack contains a 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 know more about this, I recently published a series of a parallel programming blog in F # .

+12
source share

What pmap does is create a list of 300,000 task objects, arrange them to run in parallel, and only then actually run them in parallel. In other words, one thread will sit there, creating 300,000 objects and placing them in the thread pool. Only then will they be executed.

Since your task is so trivial (multiplication and division), the overhead of creating a task, planning and processing its result is much more than just starting a calculation. This means that the async metaphor is not suitable for this operation. To do this, it is much better to use PLINQ.

+9
source share

In the calculations, this is simple, the best way is to create only a few asynchronous threads (probably one for each processor), and then calculate part of your answer. As Gabe replied, you spend all your time creating task objects.

Using this type of plan, I get accelerations that scale quite a lot in terms of the number of processors (most of them I tried 8 ... I understand that it will not scale forever)

Writing a utility for this is more than just calling PLINQ, but once you have a utility like pmap you can easily use it.

+3
source share

All Articles