“Cloud Numerics” F# Extensions

In this blog post we’ll introduce Cloud Numerics F# Extensions, a companion post to Microsoft Codename “Cloud Numerics” Lab refresh. Its purpose is to make it easier for you as an F# user to write “Cloud Numerics” applications, and it does so by wrapping “Cloud Numerics” .NET APIs to provide an F# idiomatic user experience that includes array building and manipulation and operator overloads. We’ll go through the steps of setting up the extension as well as a few examples.

The Visual Studio Solution for the extensions is available at the Microsoft Codename “Cloud Numerics” download site.

Set-Up on Systems with Visual Studio 2010 SP1

First, install “Cloud Numerics” on your local computer. If you only intend to work with compiled applications, that completes the setup. For using F# Interactive, a few additional steps are needed to enable fsi.exe for 64-bit use:

In the Programs menu, under Visual Studio Tools, right click Visual Studio x64 Win64 command prompt. Run it as administrator. In the Visual Studio tools command window, specify the following commands:

  • cd C:\Program Files (x86)\Microsoft F#\v4.0
  • copy fsi.exe fsi64.exe
  • corflags /32bit- /Force fsi64.exe

Open Visual Studio

  • From the Tools menu select Options, F# Tools, and then edit the F# Interactive Path.
  • Set the path to C:\Program Files (x86)\Microsoft F#\v4.0\fsi64.exe.
  • Restart F# Interactive.

Set-Up on Systems with Visual Studio 2012 Preview

With Visual Studio 2012 preview, it is possible to use “Cloud Numerics” assemblies locally. However, because the Visual Studio project template is not available for VS 2012 preview, you’ll have to use following procedure to bypass the installation of the template:

  • Install “Cloud Numerics” from command prompt specifying “msiexec –i MicrosoftCloudNumerics.msi CLUSTERINSTALL=1” and follow the instructions displayed by the installer for any missing prerequisites.
  • To use F# Interactive, open Visual Studio. From the Tools menu select Tools, Options, F# Tools, F# Interactive, and set “64-bit F# Interactive” to True.

Note that this procedure gives the local development experience only; you can work with 64-bit F# Interactive, and build and run your application on your PC. If you have a workstation with multiple CPU cores, you can run a compiled “Cloud Numerics” application in parallel, but deployment to Windows Azure cluster is not available.

Using Cloud Numerics F# Extensions from Your Project

To configure your F# project to use “Cloud Numerics” F# extensions:

  • Create F# Application in Visual Studio
  • From the Build menu, select Configuration Manager, and change the Platform attributes to x64

FSharpBlog1

  • In the Project menu, select the Properties <your-application-name> item. From your project’s application properties tab, ensure that the target .NET Framework is 4.0, not 4.0 Client Profile.

FSharpBlog1b

  • Add the CloudNumericsFSharpExtensions project to your Visual Studio solution
  • Add a project reference from your application to the CloudNumericsFSharpExtensions project
  • Add references to the “Cloud Numerics” managed assemblies. These assemblies are typically located in C:\Program Files\Microsoft Cloud Numerics\v0.2\Bin

FSharpBlog2

  • If you plan to deploy your application to Windows Azure, right-click on reference for FSharp.Core, and select Properties. In the properties window, set Copy Local to True.
  • Finally, you might need to edit the following in your .fs source file.
    -   The code within the #if INTERACTIVE … #endif block is required only if you’re planning to use F# Interactive.
    -   Depending on where it is located on your file system and whether you’re using Release or Debug build, you might need to adjust the path specified to CloudNumericsFSharpExtensions.

#if INTERACTIVE
#I @"C:\Program Files\Microsoft Cloud Numerics\v0.2\Bin"
#I @"..\..\..\CloudNumericsFSharpExtension\bin\x64\Release"

#r "CloudNumericsFSharpExtensions"
#r "Microsoft.Numerics.ManagedArrayImpl"
#r "Microsoft.Numerics.DenseArrays"
#r "Microsoft.Numerics.Runtime"
#r "Microsoft.Numerics.DistributedDenseArrays"
#r "Microsoft.Numerics.Math"
#r "Microsoft.Numerics.Statistics"
#r "Microsoft.Numerics.Distributed.IO"
#endif

open Microsoft.Numerics.FSharp
open Microsoft.Numerics
open Microsoft.Numerics.Mathematics
open Microsoft.Numerics.Statistics
open Microsoft.Numerics.LinearAlgebra

NumericsRuntime.Initialize()

 

Using Cloud Numerics from F# Interactive

A simple way to use “Cloud Numerics” libraries from F# Interactive is to copy and send the previous piece of code to F# Interactive. Then, you will be able to use create arrays, call functions, and so forth, for example:

> let x = DistDense.range 1.0 1000.0;;
>
val x : Distributed.NumericDenseArray<float>

> let y = ArrayMath.Sum(1.0/x);;
>
val y : float = 7.485470861

Note that when using F# Interactive, the code executes in serial fashion. However, parallel execution is straightforward as we’ll see next.

Compiling and Deploying Applications

To execute your application in parallel on your workstation, build your application, open Visual Studio x64 Win64 Command Prompt, and go to the folder where your application executable is. Then, launch a parallel MPI computation using mpiexec –n <number of processes> <application executable>.

Let’s try the above example in parallel. The application code will look like

module Example

open System
open System.Collections.Generic

#if INTERACTIVE
#I @"C:\Program Files\Microsoft Cloud Numerics\v0.2\Bin"
#I @"..\..\..\CloudNumericsFSharpExtensions\bin\x64\Release"

#r "CloudNumericsFSharpExtensions"
#r "Microsoft.Numerics.ManagedArrayImpl"
#r "Microsoft.Numerics.DenseArrays"
#r "Microsoft.Numerics.Runtime"
#r "Microsoft.Numerics.DistributedDenseArrays"
#r "Microsoft.Numerics.Math"
#r "Microsoft.Numerics.Statistics"
#r "Microsoft.Numerics.Signal"
#r "Microsoft.Numerics.Distributed.IO"
#endif

open Microsoft.Numerics.FSharp
open Microsoft.Numerics
open Microsoft.Numerics.Mathematics
open Microsoft.Numerics.Statistics
open Microsoft.Numerics.LinearAlgebra
open Microsoft.Numerics.Signal

NumericsRuntime.Initialize()

let x = DistDense.range 1.0 1000.0
let y = ArrayMath.Sum(1.0/x)
printfn "%f" y

 

You can use the same serial code in parallel case. We then run it using mpiexec to get the result:

Capture

Note!
First time you run an application using mpiexec, you might get a popup dialog: “Windows Firewall has blocked some features of this program”. Simply select “Allow access”.

 

Finally, to deploy the application to Azure we’ll re-purpose the “Cloud Numerics” C# Solution template to get to the Deployment Utility:

  1. Create a new “Cloud Numerics” C# Solution
  2. Add your F# application project to the Solution
  3. Add “Cloud Numerics” F# extensions to the Solution
  4. Set AppConfigure as the Start-Up project
  5. Build the Solution to get the “Cloud Numerics” Deployment Utility
  6. Build the F# application
  7. Use “Cloud Numerics” Deployment Utility to deploy a cluster
  8. Use the “Cloud Numerics” Deployment Utility to submit a job. Instead of the default executable, select your F# application executable to be submitted

Indexing and Assignment

F# has an elegant syntax for operating on slices of arrays. With “Cloud Numerics” F# Extensions we can apply this syntax to distributed arrays, for example:

let x = DistDense.randomFloat [10L;10L]
let y = x.[1L..3L,*]
x.[4L..6L,4L..6L] <- x.[7L..9L,7L..9L]

Operator Overloading

We supply operator overloads for matrix multiply as x *@ y and linear solve of a*x=b as let x = a /@ b . Also, operator overloads are available for element-wise operations on arrays:

  • Element-wise power: a.**b
  • Element-wise mod a.%b
  • Element-wise comparison: .= , .< , .<> and so forth.

Convenience Type Definitions

To enable a more concise syntax, we have added shortened definitions for the array classes as follows:

  • LNDA<’T> : Microsoft.Numerics.Local.DenseArray<’T>
  • DNDA<’T> : Microsoft.Numerics.Distributed.NumericDenseArray<’T>
  • LNSM<’T> : Microsoft.Numerics.Local.SparseMatrix<’T>
  • DNSM<’T> : Microsoft.Numerics.Distributed.SparseMatrix<’T>

Array Building

Finally, we provide several functions for building arrays, for example from F# sequences or by random sampling. They wrap the “Cloud Numerics” .NET APIs to for functional programming experience. The functions are within 4 modules:

  • LocalDense
  • LocalSparse
  • DistDense
  • DistSparse

These modules include functions for building arrays of specific type, for example:

let x = LocalDense.ofSeq [2;3;5;7;9]
let y = DistDense.range 10 100
let z = DistSparse.createFromTuples [(0L,3L,2.0);(1L,3L,3.0); (1L,2L, 5.0); (3L,0L,7.0)]

 

Building and Running Example Projects

The “Cloud Numerics” F# Extensions has a folder named “Examples” that holds three example .fs files, including:

  • A set of short examples that demonstrate how to invoke different library functions.
  • A latent semantic analysis example that demonstrates computation of correlations between different documents, in this case, SEC-10K filings of 30 Dow Jones companies.
  • A air traffic analysis example that demonstrates statistical analysis of flight arrival and delay data.

The examples are part of a self-contained solution. To run them:

  • Copy the four .csv input data files to C:\Users\Public\Documents (you can use a different folder, but you will need to adjust the path string in the source code to correspond to this folder).
  • In Solution Explorer, select an example to run by moving the .fs files up and down.
  • Build the example project and run it using mpiexec as explained before.

You can also run the examples in the F# interactive, by selecting code (except the module declaration on the first line) and sending it to F# interactive.

This concludes the introduction to “Cloud Numerics”  F# Extensions. We welcome your feedback at cnumerics-feedback@microsoft.com.