Blog

Archive for the ‘Best Practices’ Category

Clearing a vector

Wednesday, November 9th, 2011

A customer recently asked us for the best method to zero out a vector. We decided to run some tests to find out. Here are the five methods we tried, with any drawbacks and the timings.

These were performed on a DoubleVector, v,  of length 10,000,000.

1) Create a new vector. This isn’t really clearing out an existing vector but we thought we should include it for completeness.

 DoubleVector v2 = new DoubleVector( v.Length, 0.0 );

The big drawback here is that you’re creating new memory. Time: 419.5ms

2) Probably the first thing to come to mind is to simply iterate through the vector and set everything to zero.

for ( int i = 0; i < v.Length; i++ )
{
  v[i] = 0.0;
}

We have to do some checking in the index operator. No new memory created. Time: 578.5ms

3) In some cases, you could iterate through the underlying array of data inside the DoubleVector.

for ( int i = 0; i < v.DataBlock.Data.Length; i++ )
{
  v.DataBlock.Data[i] = 0.0;
}

This is a little less intuitive. And, very importantly, it will not work with many views into other data structures. For example, a row slice of a matrix. However, it’s easier for the CLR to optimize this loop. Time: 173.5ms

4) We can use the power of Intel’s MKL to multiply the vector by zero.

 v.Scale( 0.0 );

Scale() does this in-place. No new memory is created. In this example, we assume that MKL has already been loaded and is ready to go which is true if another MKL-based NMath call was already made or if NMath was initialized. This method will work on all views of other data structures. Time: 170ms

5) This surprised us a bit but the best method we could find was to clear out the underlying array using Array.Clear() in .NET

 Array.Clear( v.DataBlock.Data, 0, v.DataBlock.Data.Length );

This creates no new memory. However, this will not work with non-contiguous views. However, this method is very fast. Time: 85.8ms

To make this much simpler, we have created a Clear() method and a Clear( Slice) method on vectors and matrices. It will do the right thing in the right circumstance. It will be released in NMath 5.2 in 2012.

And, here is the code we used for this test:

using System;
using CenterSpace.NMath.Core;

namespace Test
{
  class ClearVector
  {
    static int size = 100000000;
    static int runs = 10;
    static int methods = 5;

    static void Main( string[] args )
    {
      System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
      DoubleMatrix times = new DoubleMatrix( runs, methods );
      NMathKernel.Init();

      for ( int run = 0; run < runs; run++ )
      {
        Console.WriteLine( "Run {0}...", run );
        DoubleVector v = null;

        // Create a new one
        v = new DoubleVector( size, 1.0, 2.0 );
        sw.Start();
        DoubleVector v2 = new DoubleVector( v.Length, 0.0 );
        sw.Stop();
        times[run, 0] = sw.ElapsedMilliseconds;
        Console.WriteLine( Assert( v2 ) );

        // iterate through vector
        v = new DoubleVector( size, 1.0, 2.0 );
        sw.Reset();
        sw.Start();
        for ( int i = 0; i < v.Length; i++ )
        {
          v[i] = 0.0;
        }
        sw.Stop();
        times[run, 1] = sw.ElapsedMilliseconds;
        Console.WriteLine( Assert( v ) );

        // iterate through array
        v = new DoubleVector( size, 1.0, 2.0 );
        sw.Reset();
        sw.Start();
        for ( int i = 0; i < v.DataBlock.Data.Length; i++ )
        {
          v.DataBlock.Data[i] = 0.0;
        }
        sw.Stop();
        times[run, 2] = sw.ElapsedMilliseconds;
        Console.WriteLine( Assert( v ) );

        // scale
        v = new DoubleVector( size, 1.0, 2.0 );
        sw.Reset();
        sw.Start();
        v.Scale( 0.0 );
        sw.Stop();
        times[run, 3] = sw.ElapsedMilliseconds;
        Console.WriteLine( Assert( v ) );

        // Array Clear
        v = new DoubleVector( size, 1.0, 2.0 );
        sw.Reset();
        sw.Start();
        Array.Clear( v.DataBlock.Data, 0, v.DataBlock.Data.Length );
        sw.Stop();
        times[run, 4] = sw.ElapsedMilliseconds;
        Console.WriteLine( Assert( v ) );
        Console.WriteLine( times.Row( run ) );
      }
      Console.WriteLine( "Means: " + NMathFunctions.Mean( times ) );
    }

    private static bool Assert( DoubleVector v )
    {
      if ( v.Length != size )
      {
        return false;
      }
      for ( int i = 0; i < v.Length; ++i )
      {
        if ( v[i] != 0.0 )
        {
          return false;
        }
      }
      return true;
    }
  }
}

- Trevor

Share

Initializing NMath

Wednesday, November 9th, 2011

NMath uses Intel’s Math Kernel Library (MKL) internally. This code contains native, optimized code to wring out the best performance possible.

There is a one-time delay when the appropriate x86 or x64 native code is loaded. This cost can be easily controlled by the developer by using the NMathKernel.Init() method. Please see Initializing NMath for more details.

- Trevor

Share

.NET curve fitting applied to putting

Monday, February 28th, 2011

“I’ve heard people say putting is 50 percent technique and 50 percent mental. I really believe it is 50 percent technique and 90 percent positive thinking. See… but that adds up to 140 percent, which is why nobody is 100 percent sure how to putt!” – Chi Chi Rodriguez

Two retired scientists, self-proclaimed duffers, came to us asking for help with their retirement project: to improve their putting using mathematics. Around the office at CenterSpace, we have been wondering if applying the fundamentals of math to the putting green might help us lower our scores this year. We sure could use some help! We will feature the results of their experiments in our quarterly newsletters throughout the year.

Armed with the NMath .NET math libraries they plan to attack the project in stages.

First, they will model the equations of motion in a simple way with the ball represented as a point, without the complications of the rotational dynamics of a real ball.

Second, they will develop a computer application to serve as a framework for solving the differential equations of motion and displaying this motion with 3d animations. For certain simple models of greens, this will allow the visualization of a putt given an initial direction and speed.

The next step will be to solve the two point boundary value problem: calculate the best initial direction and speed to get the ball into the cup at a reasonable speed. Also more complicated “real life” greens will be modeled, using least squares routines to fit known green elevation data.

“These greens are so fast I have to hold my putter over the ball and hit it with the shadow!” -Sam Snead

Finally, a more realistic model will be investigated to more precisely capture the rotational motion of a 42.67 mm ball on a grass surface.

Check out their work here…

Of course we have no illusions that this project will lower anyone’s handicap, because only hours on the golf course, the driving range and practice greens can do that. To our golfing scientist friends it’s a good excuse to both revisit the fun of their college math and physics and explore new and exciting golf courses throughout the world.

And… just maybe… seeing the ball drop in the hole on the computer will help them relieve the frustration of a morning on the real greens that we are all too familiar with!

“I would like to deny all allegations by Bob Hope that during my last game of golf, I hit an eagle, a birdie, an elk and a moose.” -Gerald Ford

Happy Retirement Guys!

Please check out some of the functionality the duffers used…

C# polynomial least squares
C# differential equations (Chapter 31). A lot more differential equation functionality is coming in June, 2011.

Share

Configuring missing values

Wednesday, October 21st, 2009

A customer asked how they could read in a CSV file into a DataFrame (for eventual linear regression) with missing values.

Share