F#
[|for index in 1 .. items.Count()-1 -> (* create object here - complex operations *)|]
C#
Object[] newItemArray= new Object[items.Count];
Parallel.For(0, items.Count, index=>
{
/*complex stuff here*/
newItemArray[index] = new Object();
});
I have the above C# and F# doing the same thing. Without the Parallel.For the F# is slightly faster. With the Parallel.For the C# takes half as long to execute. How do I properly parallelize the F# to get the same performance boost as the C#?
The way I've tried so far was Array.Parallel.Iteri, so I could use the same index into an array trick I used in C#, but it slowed it down instead of speeding it up.
Edit:
More details on what I'm doing:
I have an enumerable of byte array array array. I have another byte array array array to which I'm comparing the others. I'm sorting the enumerable on % similarity and returning the first 500.
In both the F# and the C# I'm doing a simple nested for loop which increments a counter. When done looping over a particular item in my enumerable, I create a tuple of (item, counter). Once done creating my new enumerable of (item, counter), I sort it on the counter variable, grab the first 500 and then convert back to just an enumerable of item.
The part which I'm putting inside the Parallel.For is the creation of the IEnumerable<Tuple<item, int>>
-
I guess it's time to start comparing IL...N_A– N_A2012年11月21日 03:21:43 +00:00Commented Nov 21, 2012 at 3:21
-
I know it's not easy but can you give a reproducible example? You Edit doesn't help that much.pad– pad2012年11月21日 13:59:42 +00:00Commented Nov 21, 2012 at 13:59
2 Answers 2
Array.Parallel.init items.Count (fun index ->
(* create object here - complex operations *))
Official documentation: Parallel.init<'T> Function (F#)
5 Comments
Stopwatch to time the runs and then just printing the elapsed time to the console.You shouldn't use array comprehension in this case. It's a bit slower than high-order functions and can't be parallelized.
Though I would prefer @ildjarn's solution, here is an equivalent solution to your C# one:
// You need an uninitialized array to fill in later
let newItemArray = Array.zeroCreate items.Count
// Fill in the array in a parallel manner
Array.Parallel.iteri (fun i v ->
(* create object here - complex operations *)) newItemArray
You can also use Parallel.For directly:
let newItemArray = Array.zeroCreate items.Count
Parallel.For(0, items.Count,
(fun index ->
(* complex stuff here *)
newItemArray.[index] <- Object())
) |> ignore
It's more verbose but gives you more control over degree of parallelism.
6 Comments
iteri is the first method I tried and is only slightly slower than my sequential solution. The Parallel.For solution takes about 3.5 times longer than my sequential solution.#time "on";;? It's hard to guess without more details.Parallel.For solution and .436 for the iteri solution. My sequential F# solution runs at about .360 every time.