C# Flow Control Example

← All NMath Code Examples

 

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

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

namespace CenterSpace.NMath.Core.Examples.CSharp.GPU
{
  class FlowControlExample
  {

    static void Main( string[] args )
    {

      ////////
      // Forcing work threads to a compute device.
      ///////

      // By default, the BridgeManager routes work to the most efficient device for the work issued.  However, sometimes you may want to
      // force all computation on a particular thread to run on the CPU or on a particular GPU.  This is done by called the methods ForceCPU()
      // or ForceGPU() available on the Bridge class.  Typically this would be used to offload work from the CPU to an available GPU.

      NMathConfiguration.Init();

      // 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
      {
        // Set up a string writer for logging
        using ( var writer = new StringWriter() )
        {
          // Enable the CPU /GPU bridge logging
          BridgeManager.Instance.EnableLogging( writer );

          // Assign all work for thread 1 to the GPU - never falling back to the CPU
          IComputeDevice GPU0 = BridgeManager.Instance.GetComputeDevice( 0 );
          var bridgeGPU = BridgeManager.Instance.GetBridge( GPU0 );
          bridgeGPU.ForceGpuAll();
          BridgeManager.Instance.SetBridge( GPU0, bridgeGPU );

          // Now run a matrix multiply on compute device 0.  Note that despite of the small size of
          // of the operation it takes place on the GPU because of the ForceGPUAll().
          var thread1 = new Thread( () => TimedMatrixMultiply( 101 ) );
          BridgeManager.Instance.SetComputeDevice( GPU0, thread1 );
          thread1.Start();
          thread1.Join();

          Console.WriteLine( FormatLog( writer ) );
          // 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-05 10:19:41.596 AM      4       0       dgemm         GPU     Above threshold; 101x101 = 10201 >= 0 (crossover 0)

          // Now revert back to the default bridge and re-run matrix multiply
          bridgeGPU = BridgeManager.Instance.GetBridge( GPU0 );
          bridgeGPU.RestoreDefaultRouting();
          BridgeManager.Instance.SetBridge( GPU0, bridgeGPU );

          // Now run a similar matrix multiply on compute device 0 again.
          var thread2 = new Thread( () => TimedMatrixMultiply( 102 ) );
          BridgeManager.Instance.SetComputeDevice( GPU0, thread2 );
          thread2.Start();
          thread2.Join();

          Console.WriteLine( FormatLog( writer ) );
          //        Time                    tid   Device#  Function    Device Used                  Reason
          // 2014-03-05 11:33:53.871 AM      4       0       dgemm          GPU     Above threshold; 101x101 = 10201 >= 0 (crossover 0)
          // 2014-03-05 11:33:54.127 AM      5       0       dgemm          CPU     Below threshold; 102x102 = 10404 < 640000 (crossover 800)


          // Disable logging
          BridgeManager.Instance.DisableLogging();
        }
      }
      Console.WriteLine();
      Console.WriteLine( "Press Enter Key" );
      Console.Read();
    }

    private static void TimedMatrixMultiply( int size )
    {
      var timer = new Stopwatch();
      var A = new DoubleMatrix( size, size, 0, 1 );
      timer.Reset();
      timer.Start();
      NMathFunctions.Product( A, A );
      timer.Stop();
      int taskID = Thread.CurrentThread.ManagedThreadId;
      Console.WriteLine( "Finished matrix multiplication on thread " + taskID + " of size " + size + " in (" + timer.ElapsedMilliseconds + " ms).\n" );
    }

    // 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