You forgot to pass the arguments to Vector.CrossProduct:

1
let data8 v1 v2 = Array.map2 (fun x y -> Vector.CrossProduct(x, y)) v1 v2
By on 10/11/2011 5:12 PM ()

Thanks Ramon.

I'd been looking at: [link:msdn.microsoft.com]

... but didn't see.

1
2
3
4
5
6
         

         let v1 = [|for x, y in [20.,30.; 5.,5.; 1.,1.] -> Vector(x, y)|];;
         let v2 = [|for x, y in [45.,70.; 2.,2.; 4.,4.] -> Vector(x, y)|];;

         let data8 v1 v2 = Array.map2 (fun x y -> Vector.CrossProduct(x, y)) v1 v2
1
2
3
> data8 v1 v2;;

val it : float [] = [|50.0; 0.0; 0.0|]
By on 10/12/2011 3:38 AM ()

Next I'd like to know if this makes any sense, and how do I go about implementing it...

1
 let data8 v1 v2 = Array.Parallel.map2 (fun x y -> Vector.CrossProduct(x, y)) v1 v2
By on 10/12/2011 6:46 AM ()

First, some FPish stuff (just because FPish is new, and you are new to it):

  1. You mark as answer not your comment which says "yes, you were right", but the comment which actually gives the answer.
  2. Use the markup to make your links clickable.
  3. When you have some code outside a code block, use the inline code markup (see markup help).
  4. Full markup help can be found when you click on Ask a Question or Reply and then click on the Show markup help button.

Now to your question:

The simple response to your answer would be:

1
2
Array.zip v1 v2
|> Array.Parallel.map Vector.CrossProduct

But three things should be noted about this:

  • Array.zip combined two lists: 'a list -> 'b list -> ('a * 'b) list. It is fast enough so it wouldn't matter whether or not it is paralleled.
  • As you now know, Vector.CrossProduct receives a tuple, that is why we can just give it to Parallel.map.
  • In this scenario (and various other scenarios, but not all), the parallel version is significantly slower. This is a common pitfall for people who are new with parallel computing: not everything paralleled is faster. I suggest one of these two options for learning:

    • Reading a book or taking a good university course to actually understand why are things faster and how to predict. This can also probably be done by reading several online articles - choose as you'd like.
    • Every time you think "Hey, I could do this faster with parallel!", check. It might or might not be faster, but with time you'll learn when is it faster.

How do you test is something is faster? First open F# Interactive, then turn on time, then have a loop for every idea you have to test performance. Here is what I did in order to test your case:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
> #r "WindowsBase";;

--> Referenced 'C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\WindowsBase.dll'

> #r "FSharp.PowerPack";;

--> Referenced 'C:\Program Files\FSharpPowerPack-2.0.0.0\bin\FSharp.PowerPack.dll'

> open System.Windows;;
> let v1 = [|for x, y in [20.,30.; 5.,5.; 1.,1.] -> Vector(x, y)|];;

val v1 : Vector [] = [|20,30; 5,5; 1,1|]

> let v2 = [|for x, y in [45.,70.; 2.,2.; 4.,4.] -> Vector(x, y)|];;

val v2 : Vector [] = [|45,70; 2,2; 4,4|]

> let f() = Array.Parallel.map Vector.CrossProduct (Array.zip v1 v2);;

val f : unit -> float []

> let g() = Array.map2 (fun x y -> Vector.CrossProduct (x, y)) v1 v2;;

val g : unit -> float []

> let zipped = Array.zip v1 v2;;

val zipped : (Vector * Vector) [] = [|(20,30, 45,70); (5,5, 2,2); (1,1, 4,4)|]

> let h() = Array.Parallel.map Vector.CrossProduct zipped;;

val h : unit -> float []

> #time;;

--> Timing now on

> for i = 1 to 10000 do ignore (f());;
Real: 00:00:00.329, CPU: 00:00:00.625, GC gen0: 3, gen1: 1, gen2: 0
val it : unit = ()
> for i = 1 to 10000 do ignore (f());;
Real: 00:00:00.345, CPU: 00:00:00.437, GC gen0: 16, gen1: 0, gen2: 0
val it : unit = ()
> for i = 1 to 10000 do ignore (g());;
Real: 00:00:00.008, CPU: 00:00:00.000, GC gen0: 1, gen1: 0, gen2: 0
val it : unit = ()
> for i = 1 to 10000 do ignore (g());;
Real: 00:00:00.006, CPU: 00:00:00.000, GC gen0: 0, gen1: 0, gen2: 0
val it : unit = ()
> for i = 1 to 10000 do ignore (h());;
Real: 00:00:00.427, CPU: 00:00:00.703, GC gen0: 27, gen1: 0, gen2: 0
val it : unit = ()
> for i = 1 to 10000 do ignore (h());;
Real: 00:00:00.363, CPU: 00:00:00.671, GC gen0: 30, gen1: 1, gen2: 0
val it : unit = ()

To clarify:

  1. f is the parallel version, as I proposed.
  2. g is the non-parallel version.
  3. h is the same as f, but I took the zipping out of the loop to make sure it doesn't affect performance (remember that we want to test the actual mapping, not the zipping).

Also note that I ran each loop several times (5 is usually a good number) to make sure it wasn't just a one-time glitch.

By on 10/12/2011 7:26 AM ()

Thanks again Ramon.
Re: FPish stuff -- 1. I apoligize for the mark as answer mistake ... could it be ... My IE9 browser "compatibility" mode displays differently than "regular" view. The "+/-" green red box does not display at all in compatibiliy mode. In either view I only see a "reply" box/button next to your name? "reply" "edit" "mark as answer" box/butons seem to only display next to my name?? Or maybe this cold medicine is really good. Again I apoligize and thanks for your help.

2. I like the Message preview, but I do need to learn and improve my posting markup. I'll try to do better in future.

Re: Parallel -- Thanks for the tips. I'm constatnly reminding myself to learn more. I'm exploring parallel, this post, and learning as I go. Often I fail but rush ahead anyway.

Re: Test for performance -- Thanks for your helpful reply. I know it takes some time and I do sincerely appreciate it.

I like your Array.zip v1 v2 |>. Could "||>" be used for this situation?

By on 10/12/2011 12:19 PM ()

(||>) is a great under-used operator, but beware! Operator precedence can be sometimes misleading:

1
2
3
4
5
6
7
8
// Works:
(a, b)
||> f
// Doesn't work:
a, b
||> f
// Because it is parsed as:
a, (b ||> f)
By on 10/12/2011 2:40 PM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper