C# Basic GPU Example

← All NMath Code Examples

 

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

using CenterSpace.NMath.Core;
using CenterSpace.NMath.Matrix;

namespace CenterSpace.NMath.Core.Examples.CSharp.GPU
{
  class BasicGPUExample
  {
    private static Stopwatch timer = new Stopwatch();

    static void Main( string[] args )
    {

      ////////
      // Out of the box example.
      ///////

      // Check for 32-bit process and GPU
      if ( !Environment.Is64BitProcess )
      {
        Console.WriteLine( "NMath is unable to use GPU functionality in a 32-bit process." );
      }
      else if ( BridgeManager.Instance.GPUCount == 0 )
      {
        Console.WriteLine( "NMath was unable to detect a suitable NVIDIA GPU." );
      }
      else
      {
        // The BridgeManager controls the assignment of Bridges to hardware devices, either CPUs or GPUs, and controls the assignment
        // of individual threads to particular devices.  
        using ( var writer = new StringWriter() )
        {

          // Enable logging of routing to CPU/GPU
          BridgeManager.Instance.EnableLogging( writer );

          // Out of the box, NMath Premium will run large problems on the NVIDIA device 0 GPU (if installed) and small problems on the CPU.
          // If no GPU is installed, all computation takes place on the CPU.  

          // Perform two matrix multiplications one 100 x 100 and one 1400 x 1400
          // The small one will run on the CPU and the large one on the GPU
          TimedMatrixMultiply( 100 );
          TimedMatrixMultiply( 1400 );

          // Use the logging system to verify where these matrix multiplications ran. Note that dgemm is the LAPACK name for matrix multiplication.  
          // 
          //     Time                           tid   Device#  Function    Device Used  Reason
          //     2014-03-04 01:18:53.210 PM      1       0       dgemm      CPU     Below threshold; 100x100 = 10000 < 490000 (crossover 700)
          //     2014-03-04 01:18:53.311 PM      1       0       dgemm      GPU     Above threshold; 1400x1400 = 1960000 >= 490000 (crossover 700)
          Console.WriteLine( FormatLog( writer ) );

          // Note that the first matrix multiple ran on the CPU (under Device Used) because the size was "Below threshold" and the second larger
          // multiple ran on the GPU because the size was "Above threshold".

          // Disable logging
          BridgeManager.Instance.DisableLogging();
        }

        ////////
        // Tuning for optimal performance
        ///////

        // For best performance the CPU/GPU bridge system needs to be tuned once.  Once tuned, the bridge can be stored and loaded again
        // at run time. 

        // Get the compute device assigned the device number 0.
        IComputeDevice device0 = BridgeManager.Instance.GetComputeDevice( 0 );

        if ( device0 != null )
        {
          // Start with a default bridge
          var bridge = BridgeManager.Instance.NewDefaultBridge( device0 );

          // Tune this bridge for the matrix multiply operation.  Calling TuneAll() would tune all GPU aware operations (for all precisions
          // single, double, single complex, double complex) in NMath. Depending on the sizes used, this can be an expensive operation.
          // It is intended to be run once during a calibration phase for a particular CPU/GPU combination. After completion, save
          // the resulting routing model by persisting the bridge (see below).
          bridge.Tune( BridgeFunctions.dgemm, device0, 1200 );

          // Assign the tuned bridge to GPU device 0.  If you have multiple GPU's installed, this tuned bridge could be assigned to each of
          // those devices.
          BridgeManager.Instance.SetBridge( device0, bridge );

          // Run the matrix multiply again and dump the log file
          using ( var writer = new System.IO.StringWriter() )
          {
            BridgeManager.Instance.EnableLogging( writer );
            TimedMatrixMultiply( 100 );
            TimedMatrixMultiply( 1400 );

            Console.WriteLine( FormatLog( writer ) );
            BridgeManager.Instance.DisableLogging();
          }


          ////////
          // Bridge Persistence
          ///////

          // Persisting the bridge that was tuned above is done with the BridgeManager.
          // Note that this overwrites any existing bridge with the same name.
          BridgeManager.Instance.SaveBridge( bridge, @".\MyTunedBridge" );

          // Then loading that bridge from disk is simple.
          var myTunedBridge = BridgeManager.Instance.LoadBridge( @".\MyTunedBridge" );

          // To use the bridge, assign it to an available compute device.
          BridgeManager.Instance.SetBridge( device0, myTunedBridge );
        }
      }
      Console.WriteLine();
      Console.WriteLine( "Press Enter Key" );
      Console.Read();
    }

    private static void TimedMatrixMultiply( int size )
    {
      Console.Write( "Matrix multiplication of size " + size );
      var A = new DoubleMatrix( size, size, new RandGenUniform() );
      timer.Reset();
      timer.Start();
      NMathFunctions.Product( A, A );
      timer.Stop();
      Console.WriteLine( " (" + timer.ElapsedMilliseconds + " ms)" );
    }

    // Auxiliary function for improving the readability of 
    // of the log file in the small console window.
    private static string FormatLog( StringWriter writer )
    {
      StringReader reader = new StringReader( writer.ToString() );
      string line;
      StringBuilder ret = new StringBuilder();
      ret.Append( "\nNMath Log File -----------------------------------------------------------\n" );
      ret.Append( String.Format( "Time\t\t\t\tFunction\tDevice Used\n" ) );
      reader.ReadLine();
      while ( ( line = reader.ReadLine() ) != null )
      {
        string[] parts = line.Split( '\t' );
        ret.Append( parts[0] + '\t' + parts[3] + "\t\t" + parts[5] + '\n' );
        ret.Append( "Reason: " + parts[6] + "\n\n" );
      }

      return ret.ToString();
    }
  }
}

← All NMath Code Examples
Top