<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	
	xmlns:georss="http://www.georss.org/georss"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	>

<channel>
	<title>C# Nvidia GPU Archives - CenterSpace</title>
	<atom:link href="https://www.centerspace.net/tag/c-nvidia-gpu/feed" rel="self" type="application/rss+xml" />
	<link>https://www.centerspace.net/tag/c-nvidia-gpu</link>
	<description>.NET numerical class libraries</description>
	<lastBuildDate>Tue, 07 Feb 2023 21:29:19 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.1.1</generator>
<site xmlns="com-wordpress:feed-additions:1">104092929</site>	<item>
		<title>NMath Premium&#8217;s new Adaptive GPU Bridge Architecture</title>
		<link>https://www.centerspace.net/gpu-math-csharp</link>
					<comments>https://www.centerspace.net/gpu-math-csharp#respond</comments>
		
		<dc:creator><![CDATA[Paul Shirkey]]></dc:creator>
		<pubDate>Mon, 13 Oct 2014 16:35:01 +0000</pubDate>
				<category><![CDATA[NMath Premium]]></category>
		<category><![CDATA[.NET GPU]]></category>
		<category><![CDATA[C# GPU]]></category>
		<category><![CDATA[c# LAPACK GPU]]></category>
		<category><![CDATA[C# Nvidia GPU]]></category>
		<category><![CDATA[math gpu]]></category>
		<category><![CDATA[math gpu csharp]]></category>
		<category><![CDATA[NMath GPU]]></category>
		<category><![CDATA[Offloading to GPU]]></category>
		<guid isPermaLink="false">http://www.centerspace.net/blog/?p=5295</guid>

					<description><![CDATA[<p>The most release of NMath Premium 6.0 is a major upgrade to the GPU API and it enables users to easily use multiple installed NVIDIA GPU's.  As always, using NMath Premium to leverage GPU's never requires any kernel-level GPU programming or other specialized GPU programming skills.  In the following article, after introducing the new GPU bridge architecture, we'll discuss each of the new API features separately with code examples.</p>
<p>The post <a rel="nofollow" href="https://www.centerspace.net/gpu-math-csharp">NMath Premium&#8217;s new Adaptive GPU Bridge Architecture</a> appeared first on <a rel="nofollow" href="https://www.centerspace.net">CenterSpace</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The most recent release of NMath Premium 6.0 is a major update which includes an upgraded optimization suite, now backed by the Microsoft Solver Foundation, a significantly more powerful GPU-bridge architecture, and a new class for cubic smoothing splines. This blog post will focus on the new API for doing computation on GPU&#8217;s with NMath Premium. </p>
<p>The adaptive GPU bridge API in NMath Premium 6.0 includes the following important new features.</p>
<section>
<ul>
<li>Support for multiple GPU&#8217;s</li>
<li>Automatic tuning of the CPU&#8211;GPU adaptive bridge to insure optimal hardware usage.</li>
<li>Per-thread control for binding threads to GPU&#8217;s.</li>
</ul>
</section>
<p>As with the first release of NMath Premium, using NMath to leverage massively-parallel GPU&#8217;s never requires any kernel-level GPU programming or other specialized GPU programming skills. Yet the programmer can easily take as much control as needed to route executing threads or tasks to any available GPU device. In the following, after introducing the new GPU bridge architecture, we&#8217;ll discuss each of these features separately with code examples.</p>
<p>Before getting started on our NMath Premium tutorial it&#8217;s important to consider your test GPU model.  While many of NVIDIA&#8217;s GPU&#8217;s provide a good to excellent computational advantage over the CPU, not all of NVIDIA&#8217;s GPU&#8217;s were designed with general computing in mind. The &#8220;NVS&#8221; class of NVIDIA GPU&#8217;s (such as the NVS 5400M) generally perform very poorly as do the &#8220;GT&#8221; cards in the GeForce series. However the &#8220;GTX&#8221; cards in the <a href="http://www.geforce.com/hardware" target="_blank">GeForce series</a> generally perform well, as do the Quadro Desktop Produces and the Tesla cards. While it&#8217;s fine to test NMath Premium on any NVIDIA, testing on inexpensive consumer grade video cards will rarely show any performance advantage.</p>
<h3>NMath&#8217;s GPU API Basics</h3>
<p>With NMath there are three fundamental software entities involved with routing computations between the CPU and GPU&#8217;s: GPU hardware devices represented by <code>IComputeDevice</code> instances, the <code>Bridge</code> classes which control when a particular operation is sent to the CPU or a GPU, and finally the <code>BridgeManager</code> which provides the primary means for managing the devices and bridges.</p>
<p>These three entities are governed by two important ideas.</p>
<ol>
<li><code>Bridges</code> are assigned to compute devices and there is a strict one-to-one relationship between each <code>Bridge</code> and <code>IComputeDevice</code>. Once assigned, the bridge instance governs when computations will be sent to it&#8217;s paired GPU device or the CPU.</li>
<li>Executing threads are assigned to devices; this is a many-to-one relationship. Any number of threads can be routed to a particular compute device.</li>
</ol>
<p>Assigning a <code>Bridge</code> class to a device is one line of code with the <code>BridgeManager</code>.</p>
<pre lang="csharp">BridgeManager.Instance.SetBridge( BridgeManager.Instance.GetComputeDevice( 0 ), bridge );</pre>
<p>Assigning a thread, in this case the <code>CurrentThread</code>, to a device is again accomplished using the <code>BridgeManager</code>.</p>
<pre lang="csharp">IComputeDevice cd = BridgeManager.Instance.GetComputeDevice( 0 );
BridgeManager.Instance.SetComputeDevice( cd, Thread.CurrentThread );</pre>
<p>After installing NMath Premium, the default behavior will create a default bridge and assign it to the GPU with a device number of 0 (generally the fastest GPU installed). Also by default, all unassigned threads will execute on device 0. This means that out of the box with no additional programming, existing NMath code, once recompiled against the new NMath Premium assemblies, will route all appropriate computations to the device 0 GPU. All of the follow discussions and code examples are ways to refine this default behavior to get the best performance from your GPU hardware.</p>
<h3>Math on Multiple GPU&#8217;s Supported</h3>
<p>Currently only the NVIDIA GPU with a device number 0 is supported by NMath Premium, this release removes that barrier. With version 6, work can be assigned to any installed NVIDIA device as long as the device drivers are up-to-date.</p>
<p>The work done by an executing thread is routed to a particular device using the <code>BridgeManager.Instance.SetDevice()</code> as we saw in the example above. Any properly configured hardware device can be used here including any NVIDIA device and the CPU. The CPU is simply viewed as another compute device and is always assigned a device number of -1.</p>
<pre lang="csharp" line="1">var bmanager = BridgeManager.Instance;

var cd = bmanager .GetComputeDevice( -1 );
BridgeManager.Instance.SetComputeDevice( cd, Thread.CurrentThread );
....
cd = bmanager .GetComputeDevice( 2 );
BridgeManager.Instance.SetComputeDevice( cd, Thread.CurrentThread );</pre>
<p>Lines 3 &#038; 4 first assign the current thread to the CPU device (no code on this thread will run on any GPU) and then in lines 6 &#038; 7 the current thread is switched to the GPU device 2.  If an invalid compute device is requested a null <code>IComputeDevice</code> is returned.  To find all available computing devices, the <code>BridgeManager</code> offers an array of <code>IComputeDevices</code> which contains all detected compute devices <em>including the CPU</em>, called <code>IComputeDevices Devices[]</code>. The number of detected GPU&#8217;s can be found using the property <code>BridgeManager.Instance.CountGPU</code>.</p>
<p>As an aside, keep in mind that PCI slot numbers do not necessarily correspond to GPU device numbers. NVIDIA assigns the device number 0 to the fastest detected GPU and so installing an additional GPU into a machine may renumber the device numbers for the previously installed GPU&#8217;s.</p>
<h3>Tuning the Adaptive Bridge</h3>
<p>Assigning a <code>Bridge</code> to a GPU device doesn&#8217;t necessarily mean that all computation routed to that device will run on that device. Instead, the assigned <code>Bridge</code> acts as an intermediary between the CPU and the GPU and moves the larger problems to the GPU where there&#8217;s a speed advantage and retains the smaller problems on the CPU. NMath has a built-in default bridge, but it may generate non-optimal run-times depending on your hardware or your customers hardware configuration. To improved the hardware usage and performance a bridge can be tuned once and then persisted to disk for all future use.</p>
<pre lang="csharp">// Get a compute device and a new bridge.
IComputeDevice cd = BridgeManager.Instance.GetComputeDevice( 0 );
Bridge bridge = BridgeManager.Instance.NewDefaultBridge( cd );

// Tune this bridge for the matrix multiply operation alone. 
bridge.Tune( BridgeFunctions.dgemm, cd, 1200 );

// Or just tune the entire bridge.  Depending on the hardware and tuning parameters
// this can be an expensive one-time operation. 
bridge.TuneAll( cd, 1200 );

// Now assign this updated bridge to the device.
BridgeManager.Instance.SetBridge( cd, bridge );

// 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" );</pre>
<p>Once a bridge is tuned it can be persisted, redistributed, and used again. If three different GPU&#8217;s are installed this tuning should be done once for each GPU and then each bridge should be assigned to the device it was tuned on. However if there are three identical GPU&#8217;s the tuning need be done only once, then persisted to disk, and later assigned to all identical GPU&#8217;s. Bridges assigned to GPU devices for which it wasn&#8217;t tuned will never result in incorrect results, only possibly under performance of the hardware.</p>
<h3>Thread Control</h3>
<p>Once a bridge is paired to a device, threads may be assigned to that device for execution. This is not a necessary step as all unassigned threads will run on the default device (typically device 0). However, suppose we have three tasks and three GPU&#8217;s, and we wish to use a GPU per task.  The following code does that.</p>
<pre lang="csharp">...
IComputeDevice gpu0= BridgeManager.Instance.GetComputeDevice( 0 );
IComputeDevice gpu1 = BridgeManager.Instance.GetComputeDevice( 1 );
IComputeDevice gpu2 = BridgeManager.Instance.GetComputeDevice( 2 );

if( gpu0 != null && gpu1 != null && gpu2 != null)
{
   System.Threading.Tasks.Task[] tasks = new Task[3]
   {
      Task.Factory.StartNew(() => Task1Worker(gpu0)),
      Task.Factory.StartNew(() => Task2Worker(gpu1)),
      Task.Factory.StartNew(() => Task2Worker(gpu2)),
   };

   //Block until all tasks complete.
   Task.WaitAll(tasks);
}
...</pre>
<p>This code is standard C# code using the <a href="https://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspx" target="_blank">Task Parallel Library</a> and contains no NMath Premium specific API calls outside of passing a GPU compute device to each task. The task worker routines have the following simple structure.</p>
<pre lang="csharp">private static void Task1Worker( IComputeDevice cd  )
  {
      BridgeManager.Instance.SetComputeDevice( cd );

      // Do Work here.
  }</pre>
<p>The other two task workers are identical outside of whatever useful computing work they may be doing.</p>
<p>Good luck and please post any questions in the comments below or just email us at support AT centerspace.net we&#8217;ll get back to you.</p>
<p>Happy Computing,</p>
<p>Paul</p>
<p>The post <a rel="nofollow" href="https://www.centerspace.net/gpu-math-csharp">NMath Premium&#8217;s new Adaptive GPU Bridge Architecture</a> appeared first on <a rel="nofollow" href="https://www.centerspace.net">CenterSpace</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.centerspace.net/gpu-math-csharp/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">5295</post-id>	</item>
		<item>
		<title>Distributing Parallel Tasks on Multiple GPU&#8217;s</title>
		<link>https://www.centerspace.net/tasks-on-gpu</link>
					<comments>https://www.centerspace.net/tasks-on-gpu#respond</comments>
		
		<dc:creator><![CDATA[Paul Shirkey]]></dc:creator>
		<pubDate>Wed, 17 Sep 2014 20:50:51 +0000</pubDate>
				<category><![CDATA[NMath Premium]]></category>
		<category><![CDATA[.NET GPU]]></category>
		<category><![CDATA[C# GPU]]></category>
		<category><![CDATA[c# LAPACK GPU]]></category>
		<category><![CDATA[C# Nvidia GPU]]></category>
		<category><![CDATA[math gpu]]></category>
		<category><![CDATA[math gpu csharp]]></category>
		<category><![CDATA[NMath GPU]]></category>
		<category><![CDATA[Offloading to GPU's]]></category>
		<guid isPermaLink="false">http://www.centerspace.net/blog/?p=5397</guid>

					<description><![CDATA[<p><img class="excerpt" alt="NMath Premium" src="/themes/centerspace/images/nmath-premium.png" /> Once Microsoft published the <code>Threading.Task</code> library with .NET 4 many programmers who never or only occasionally wrote multi-threaded code were now doing so regularly with the <code>Threading.Task</code> API.  The Task library reduced the complexity of writing threaded code and provided a several new related classes to make the process easier while eliminating some pitfalls.  In this post I'm going to show how to use the Task library with NMath Premium 6.0 to run tasks in parallel on multiple GPU's and the CPU.</p>
<p>The post <a rel="nofollow" href="https://www.centerspace.net/tasks-on-gpu">Distributing Parallel Tasks on Multiple GPU&#8217;s</a> appeared first on <a rel="nofollow" href="https://www.centerspace.net">CenterSpace</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>In this post I&#8217;m going demonstrate how to use the Task Parallel Library with NMath Premium to run tasks in parallel on multiple GPU&#8217;s and the CPU.  Back in 2012 when Microsoft released .NET 4.0 and the <code>System.Threading.Task</code> namespace many .NET programmers never, or only under duress, wrote multi-threaded code.  It&#8217;s old news now that <a href="https://msdn.microsoft.com/en-us/library/dd460693(v=vs.100).aspx" target="_blank">TPL</a> has reduced the complexity of writing threaded code by providing several new classes to make the process easier while eliminating some pitfalls.  Leveraging the TPL API together with NMath Premium is a powerful combination for quickly getting code running on your GPU hardware without the burden of learning complex CUDA programming techniques.</p>
<h2> NMath Premium GPU Smart Bridge</h2>
<p>The NMath Premium 6.0 library is now integrated with a new CPU-GPU hybrid-computing Adaptive Bridge&trade; Technology.  This technology allows users to easily assign specific threads to a particular compute device and manage computational routing between the CPU and multiple on-board GPU&#8217;s.  Each piece of installed computing hardware is uniformly treated as a compute device and managed in software as an immutable <code>IComputeDevice</code>;  Currently the adaptive bridge allows a single CPU compute device (naturally!) along with any number of NVIDIA GPU devices.  How NMath Premium interacts with each compute device is governed by a <code>Bridge</code> class.  A one-to-one relationship between each <code>Bridge</code> instance and each compute device is enforced.  All of the compute devices and bridges are managed by the singleton <code>BridgeManager</code> class.</p>
<figure id="attachment_5473" aria-describedby="caption-attachment-5473" style="width: 600px" class="wp-caption alignnone"><img decoding="async" src="https://www.centerspace.net/blog/wp-content/uploads/2014/04/Adaptive-Bridge.png" alt="Adaptive Bridge" width="600" class="size-full wp-image-5473" srcset="https://www.centerspace.net/wp-content/uploads/2014/04/Adaptive-Bridge.png 700w, https://www.centerspace.net/wp-content/uploads/2014/04/Adaptive-Bridge-300x186.png 300w" sizes="(max-width: 700px) 100vw, 700px" /><figcaption id="caption-attachment-5473" class="wp-caption-text">Adaptive Bridge</figcaption></figure>
<p>These three classes: the <code>BridgeManager</code>, the <code>Bridge</code>, and the immutable <code>IComputeDevice</code> form the entire API of the Adaptive Bridge&trade;.  With this API, nearly all programming tasks, such as assigning a particular <code>Action<></code> to a specific GPU, are accomplished in one or two lines of code.  Let&#8217;s look at some code that does just that:  Run an <code>Action<></code> on a GPU.</p>
<pre lang="csharp">
using CenterSpace.NMath.Matrix;

public void mainProgram( string[] args )
    {
      // Set up a Action<> that runs on a IComputeDevice.
      Action<IComputeDevice, int> worker = WorkerAction;
      
      // Get the compute devices we wish to run our 
      // Action<> on - in this case two GPU 0.
      IComputeDevice deviceGPU0 = BridgeManager.Instance.GetComputeDevice( 0 );

      // Do work
      worker(deviceGPU0, 9);
    }

    private void WorkerAction( IComputeDevice device, int input )
    {
      // Place this thread to the given compute device.
      BridgeManager.Instance.SetComputeDevice( device );

      // Do all the hard work here on the assigned device.
      // Call various GPU-aware NMath Premium routines here.
      FloatMatrix A = new FloatMatrix( 1230, 900, new RandGenUniform( -1, 1, 37 ) );
      FloatSVDecompServer server = new FloatSVDecompServer();
      FloatSVDDecomp svd = server.GetDecomp( A );
    }
</pre>
<p>It&#8217;s important to understand that only operations where the GPU has a computational advantage are actually run on the GPU.  So it&#8217;s not as though all of the code in the <code>WorkerAction</code> runs on the GPU, but only code that makes sense such as: SVD, QR decomp, matrix multiply, Eigenvalue decomposition and so forth.  But using this as a code template, you can easily run your own worker several times passing in different compute devices each time to compare the computational advantages or disadvantages of using various devices &#8211; including the CPU compute device.</p>
<p>In the above code example the <code>BridgeManager</code> is used twice: once to get a <code>IComputeDevice</code> reference and once to assign a thread (the <code>Action<>'s</code> thread in this case ) to the device.  The <code>Bridge</code> class didn&#8217;t come into play since we implicitly relied on a default bridge to be assigned to our compute device of choice.  Relying on the default bridge will likely result in inferior performance so it&#8217;s best to use a bridge that has been specifically tuned to your NVIDIA GPU.  The follow code shows how to accomplish bridge tuning.</p>
<pre lang="csharp">
  // Here we get the bridge associated with GPU device 0.
  var cd = BridgeManager.Instance.GetComputeDevice( 0 );
  var bridge = (Bridge) BridgeManager.Instance.GetBridge( cd );

  // Tune the bridge and save it.  Turning can take a few minutes.
  bridge.TuneAll( device, 1200 );
  bridge.SaveBridge("Device0Bridge.bdg");
</pre>
<p>This bridge turning is typically a one-time operation per computer, and once done, the tuned bridge can be serialized to disk and then reload at application start-up.  If new GPU hardware is installed then this tuning operation should be repeated.  The following code snipped loads a saved bridge and pairs it with a device.</p>
<pre lang="csharp">
  // Load our serialized bridge.
  Bridge bridge = BridgeManager.Instance.LoadBridge( "Device0Bridge.bdg" );
  
  // Now pair this saved bridge with compute device 0.   
  var device0 = BridgeManager.Instance.GetComputeDevice( 0 );
  BridgeManager.Instance.SetBridge( device0, bridge );
</pre>
<p>Once the tuned bridge is assigned to a device, the behavior of all threads assigned to that device will be governed by that bridge.  In the typical application the pairing of bridges to devices done at start up and not altered again, while the assignment of threads to devices may be done frequently at runtime.</p>
<p>It&#8217;s interesting to note that beyond optimally routing small and large problems to the CPU and GPU respectively, bridges can be configured to shunt all work to the GPU regardless of problem size.  This is useful for testing and for offloading work to a GPU when the CPU if taxed.  Even if the particular problem runs slower on the GPU than the CPU, if the CPU is fully occupied, offloading work to an otherwise idle GPU will enhance performance.</p>
<h2> C# Code Example of Running Tasks on Two GPU&#8217;s </h2>
<p>I&#8217;m going to wrap up this blog post with a complete C# code example which runs a matrix multiplication task simultaneously on two GPU&#8217;s and the CPU.  The framework of this example uses the TPL and aspects of the adaptive bridge already covered here.  I ran this code on a machine with two NVIDIA GeForce GPU&#8217;s, a GTX760 and a GT640, and the timing results from this run for executing a large matrix multiplication are shown below.</p>
<pre class="code">
Finished matrix multiply on the GeForce GTX 760 in 67 ms.
Finished matrix multiply on the Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz in 103 ms.
Finished matrix multiply on the GeForce GT 640 in 282 ms.

Finished all double precision matrix multiplications in parallel in 282 ms.
</pre>
<p>The complete code for this example is given in the section below.  In this run we see the GeForce GTX760 easily finished first in 67ms followed by the CPU and then finally by the GeForce GT640.  It&#8217;s expected that the GeForce GT640 would not do well in this example because it&#8217;s optimized for single precision work and these matrix multiples are double precision.  Nevertheless, this examples shows it&#8217;s programmatically simple to push work to any NVIDIA GPU and in a threaded application even a relatively slow GPU can be used to offload work from the CPU.  Also note that the entire program ran in 282ms &#8211; the time required to finish the matrix multiply by the slowest hardware &#8211; verifying that all three tasks did run in parallel and that there was very little overhead in using the TPL or the Adaptive Bridge&trade;</p>
<p>Below is a snippet of the NMath Premium log file generated during the run above.</p>
<pre class="code">
	Time 		        tid   Device#  Function    Device Used    
2014-04-28 11:22:47.417 AM	10	0	dgemm		GPU
2014-04-28 11:22:47.421 AM	15	1	dgemm		GPU
2014-04-28 11:22:47.425 AM	13	-1	dgemm		CPU
</pre>
<p>We can see here that three threads were created nearly simultaneously with thread id&#8217;s of 10, 15, &#038; 13;  And that the first two threads ran their matrix multiplies (dgemm) on  GPU&#8217;s 0 and 1 and the last thread 13 ran on the CPU.  As a matter of convention the CPU device number is always -1 and all GPU device numbers are integers 0 and greater.  Typically device number 0 is assigned to the fastest installed GPU and that is the default GPU used by NMath Premium.  </p>
<p>-Paul</p>
<h3> TPL Tasks on Multiple GPU&#8217;s C# Code </h3>
<pre lang="csharp">
public void GPUTaskExample()
    {
     
      NMathConfiguration.Init();

      // Set up a string writer for logging
      using ( var writer = new System.IO.StringWriter() )
      {

        // Enable the CPU/GPU bridge logging
        BridgeManager.Instance.EnableLogging( writer );

        // Get the compute devices we wish to run our tasks on - in this case 
        // two GPU's and the CPU.
        IComputeDevice deviceGPU0 = BridgeManager.Instance.GetComputeDevice( 0 );
        IComputeDevice deviceGPU1 = BridgeManager.Instance.GetComputeDevice( 1 );
        IComputeDevice deviceCPU = BridgeManager.Instance.CPU;

        // Build some matrices
        var A = new DoubleMatrix( 1200, 1400, 0, 1 );
        var B = new DoubleMatrix( 1400, 1300, 0, 1 );

        // Build the task array and assign matrix multiply jobs and compute devices
        // to those tasks.  Any number of tasks can be added here and any number 
        // of tasks can be assigned to a particular device.
        Stopwatch timer = new Stopwatch();
        timer.Start();
        System.Threading.Tasks.Task[] tasks = new Task[3]
        {
          Task.Factory.StartNew(() => MatrixMultiply(deviceGPU0, A, B)),
          Task.Factory.StartNew(() => MatrixMultiply(deviceGPU1, A, B)),
          Task.Factory.StartNew(() => MatrixMultiply(deviceCPU, A, B)),
        };

        // Block until all tasks complete
        Task.WaitAll( tasks );
        timer.Stop();
        Console.WriteLine( "Finished all double precision matrix multiplications in parallel in " + timer.ElapsedMilliseconds + " ms.\n" );

        // Dump the log file for verification.
        Console.WriteLine( writer );

        // Quit logging
        BridgeManager.Instance.DisableLogging();
      
      }
    }

    private static void MatrixMultiply( IComputeDevice device, DoubleMatrix A, DoubleMatrix B )
    {
      // Place this thread to the given compute device.
      BridgeManager.Instance.SetComputeDevice( device );

      Stopwatch timer = new Stopwatch();
      timer.Start();

      // Do this task work.
      NMathFunctions.Product( A, B );

      timer.Stop();
      Console.WriteLine( "Finished matrix multiplication on the " + device.DeviceName  + " in " + timer.ElapsedMilliseconds + " ms.\n" );
    }
    
</pre>
<pre lang="csharp">

</pre>
<p>The post <a rel="nofollow" href="https://www.centerspace.net/tasks-on-gpu">Distributing Parallel Tasks on Multiple GPU&#8217;s</a> appeared first on <a rel="nofollow" href="https://www.centerspace.net">CenterSpace</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.centerspace.net/tasks-on-gpu/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">5397</post-id>	</item>
		<item>
		<title>Detecting and Configuring your GPU for Computation</title>
		<link>https://www.centerspace.net/detecting-and-configuring-your-gpu-for-computation</link>
					<comments>https://www.centerspace.net/detecting-and-configuring-your-gpu-for-computation#respond</comments>
		
		<dc:creator><![CDATA[Paul Shirkey]]></dc:creator>
		<pubDate>Wed, 19 Jun 2013 15:30:03 +0000</pubDate>
				<category><![CDATA[NMath Premium]]></category>
		<category><![CDATA[C# GPU]]></category>
		<category><![CDATA[C# Nvidia GPU]]></category>
		<category><![CDATA[deviceQuery]]></category>
		<category><![CDATA[GPU Setup]]></category>
		<category><![CDATA[NVIDIA deviceQuery]]></category>
		<category><![CDATA[NVIDIA GPU drivers]]></category>
		<guid isPermaLink="false">http://www.centerspace.net/blog/?p=4591</guid>

					<description><![CDATA[<p>Before evaluating NMath Premium or any other GPU-aware software you need to know what type of hardware you have and verify that the correct drivers are installed. There are two quick ways of detecting your NVIDIA GPU and viewing it's hardware specifications.</p>
<p>The post <a rel="nofollow" href="https://www.centerspace.net/detecting-and-configuring-your-gpu-for-computation">Detecting and Configuring your GPU for Computation</a> appeared first on <a rel="nofollow" href="https://www.centerspace.net">CenterSpace</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2> Detecting your GPU </h2>
<p>Before evaluating NMath Premium or any other GPU-aware software you need to know what type of hardware you have and verify that the correct drivers are installed. There are two quick ways of detecting your NVIDIA GPU and viewing it&#8217;s hardware specifications.</p>
<ol>
<li>
The majority of installed NVIDIA GPU&#8217;s in desktop computers are there acting as high performance video rendering hardware.  You can quickly see if you have a NVIDIA GPU installed by opening your windows <it>Device Manager</it> (right click on Computer from the Start menu, select Properties, and click on Device Manger).  Once in the <it>Device Manager</it> open the Display adapters in the tree-menu and a list of installed devices will be shown. On my development machine I see one display adapter listed as &#8220;NVIDIA GeForce GT 640&#8221;.  </p>
<table>
<tr>
<td>
<a href="https://www.centerspace.net/blog/wp-content/uploads/2013/06/DeviceManager.png"><img decoding="async" loading="lazy" src="https://www.centerspace.net/blog/wp-content/uploads/2013/06/DeviceManager.png" alt="My device manager" width="324" height="366" class="alignnone size-full wp-image-4608" srcset="https://www.centerspace.net/wp-content/uploads/2013/06/DeviceManager.png 324w, https://www.centerspace.net/wp-content/uploads/2013/06/DeviceManager-265x300.png 265w" sizes="(max-width: 324px) 100vw, 324px" /></a>
</td>
</tr>
</table>
<p>Multiple display adapters can be installed and it&#8217;s important to note that <em>NMath Premium</em> currently only runs on the <code>device 0</code> adapter.  By right clicking on a listed display adapter more details are provided including the driver version and device number.  Display adapters (GPU&#8217;s) can be individually enabled or disabled from the right-click context menu.
</li>
<li>
NVIDIA provides a GPU device query program called <code>DeviceQuery.exe</code> that is freely available which gives a detailed list of features of all installed GPU&#8217;s.  CenterSpace ships a version of this program with the GPU-aware <em>NMath Premium</em> product.  When I run this program on my development machine I get the following:</p>
<pre class="code">
CenterSpace Software NMath Premium Check...

Detected 1 CUDA Capable device(s)

Device 0: "GeForce GT 640"
  CUDA Driver Version / Runtime Version          5.5 / 5.0
  CUDA Capability Major/Minor version number:    3.0
  Total amount of global memory:                 1024 MBytes (107...
  ( 2) Multiprocessors x (192) CUDA Cores/MP:    384 CUDA Cores
  GPU Clock rate:                                954 MHz (0.95 GHz)
  Memory Clock rate:                             2500 Mhz
  Memory Bus Width:                              128-bit
  L2 Cache Size:                                 262144 bytes
  Max Texture Dimension Size (x,y,z)             1D=(65536), 2D=(65...
  Max Layered Texture Size (dim) x layers        1D=(16384) x 2048,...
  Total amount of constant memory:               65536 bytes
  Total amount of shared memory per block:       49152 bytes
  Total number of registers available per block: 65536
  Warp size:                                     32
  Maximum number of threads per multiprocessor:  2048
  Maximum number of threads per block:           1024
  Maximum sizes of each dimension of a block:    1024 x 1024 x 64
  Maximum sizes of each dimension of a grid:     2147483647 x 655...
  Maximum memory pitch:                          2147483647 bytes
  Texture alignment:                             512 bytes
  Concurrent copy and kernel execution:          Yes with 1 copy e...
  Run time limit on kernels:                     Yes
  Integrated GPU sharing Host Memory:            No
  Support host page-locked memory mapping:       Yes
  Alignment requirement for Surfaces:            Yes
  Device has ECC support:                        Disabled
  Device supports Unified Addressing (UVA):      Yes
  Device PCI Bus ID / PCI location ID:           1 / 0
  Compute Mode:
     < Default (multiple host threads can use ::cudaSetDevice() 
       with device simultaneously) >

deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 5.5, 
CUDA Runtime Version = 5.0, NumDevs = 1, Device0 = GeForce GT 640
</pre>
<p>Note that <code>deviceQuery</code> has a CUDA library dependency (on the runtime CUDART64 dll) and so will complain unless you have installed <em>NMath Premium</em>.  Probably the most important item to note is at the bottom of the listing where the CUDA driver and CUDA runtimes versions are given.  Currently <em>NMath Premium</em> requires a CUDA driver of at least 5.0 and a CUDA runtime of the same version or higher.  I&#8217;ll describe the simple process of upgrading your driver in the follow section.
</li>
</ol>
<h2> NVIDIA GPU Drivers </h2>
<p>NVIDIA has made upgrading to the latest driver simple and you&#8217;ll need to do this upgrade to use <em>NMath Premium</em> if your CUDA driver is below 5.0.  If you have a GeForce GPU just point your browser at <a href=" http://www.geforce.com/drivers" title=" http://www.geforce.com/drivers"> http://www.geforce.com/drivers</a> and the site can automatically detect your hardware and download the latest correct driver.  Alternatively the latest drivers for all NVIDIA hardware are available for download <a href="http://www.nvidia.com/Download/index.aspx?lang=en-us" title="Nvidia driver download page">here</a>.</p>
<h2> Compute Capability  </h2>
<p>NVIDIA has classified it&#8217;s various hardware architectures under the moniker of <it>Compute Capability</it>.  The higher the compute capability number a GPU has the more modern it&#8217;s architecture.  Most software leveraging NVIDIA GPU&#8217;s requires some minimum compute capability to run correctly and <em>NMath Premium</em> is no different.  <em>NMath Premium</em> requires a GPU with a compute capability of 1.3 or higher.  All of NVIDIA&#8217;s GPUs are listed <a href="https://developer.nvidia.com/cuda-gpus">here</a> along with their compute capability number.  The <code>deviceQuery</code> also lists each installed GPU&#8217;s compute capability near the head of the listing under <code>CUDA Capability Major/Minor version number</code> (see above).</p>
<p>The post <a rel="nofollow" href="https://www.centerspace.net/detecting-and-configuring-your-gpu-for-computation">Detecting and Configuring your GPU for Computation</a> appeared first on <a rel="nofollow" href="https://www.centerspace.net">CenterSpace</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.centerspace.net/detecting-and-configuring-your-gpu-for-computation/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4591</post-id>	</item>
		<item>
		<title>Offloading Computation to your GPU</title>
		<link>https://www.centerspace.net/offloading-computation-to-your-gpu</link>
					<comments>https://www.centerspace.net/offloading-computation-to-your-gpu#respond</comments>
		
		<dc:creator><![CDATA[Paul Shirkey]]></dc:creator>
		<pubDate>Thu, 13 Jun 2013 22:32:35 +0000</pubDate>
				<category><![CDATA[NMath Premium]]></category>
		<category><![CDATA[C# GPU]]></category>
		<category><![CDATA[C# Nvidia GPU]]></category>
		<category><![CDATA[Offloading to GPU]]></category>
		<guid isPermaLink="false">http://www.centerspace.net/blog/?p=4473</guid>

					<description><![CDATA[<p>Large computational problems are offloaded onto a GPU because the problems run substantially faster on the GPU than on the CPU. By leveraging the innate parallelism of the GPU overall performance of the application is improved. (For example, see here and here.) However a second collateral benefit of moving computation to the GPU is the [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.centerspace.net/offloading-computation-to-your-gpu">Offloading Computation to your GPU</a> appeared first on <a rel="nofollow" href="https://www.centerspace.net">CenterSpace</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Large computational problems are offloaded onto a GPU because the problems run substantially faster on the GPU than on the CPU. By leveraging the innate parallelism of the GPU overall performance of the application is improved. (For example, see <a href="https://web.archive.org/web/20160329160744/http://www.centerspace.net:80/nmath-premium-gpu-accelerated-performance-test">here </a>and <a href="/nmath-premium-fft-performance/">here</a>.) However a second collateral benefit of moving computation to the GPU is the resulting offloading of computation from the CPU. But, until the advent of tools like <strong>NMath Premium</strong>, this benefit has been seldom discussed because of the complexity of programming the GPU; raw performance of the GPU has been the focus but for desktop users the ability to offload work to a second underutilized processor is often just as important. In this post I&#8217;ll present a code example that provides a simple task queuing model that can asynchronously offload work to the GPU and return results without writing any specialized GPU code.</p>
<h2>Offloading to Your GPU</h2>
<p>Frequently data processing applications have a tripartite structure &#8211; the data flows in from a disk on the network, the data is then computationally processed, and finally the results are analyzed and exported. Each of these tasks has various computational loads and each can be completed independently. In the code example below, this common structure is mirrored in three asynchronous tasks, one for each of the above described tasks, linked by two queues. We want to compute a stream of 2D FFT&#8217;s and would like to offload that work to the GPU to free up the CPU for more analysis.</p>
<pre lang="csharp">    public void ThreadedGPUFFTExample()
    {

      //NMathConfiguration.ProcessorSharingMethod = ProcessorManagement.CPU;
      //NMathConfiguration.EnableGPULogging = true;

      Stopwatch timer = new Stopwatch();
      timer.Reset();

      // Off-load all FFT work to the GPU.
      var fftLength = 3000;
      FloatComplexForward2DFFT fftEngine = 
          new FloatComplexForward2DFFT( fftLength, fftLength );

      Queue dataInQ = new Queue( 2 );
      Queue dataOutQ = new Queue( 10 );

      var jobBlockCount = 10;

      // Start up threaded tasks that each monitor their respective Queues.
      var fftTask = Task.Factory.StartNew( () 
          = GPUFFTWorker( jobBlockCount, fftEngine, dataInQ, dataOutQ ) );
      var cpuTask = Task.Factory.StartNew( () 
          = CPUWorker( jobBlockCount, dataOutQ ) );
      var cpuDataReaderTask = Task.Factory.StartNew( () 
          = CPUDataReader( jobBlockCount, dataInQ ) );

      timer.Start();
      cpuTask.Wait();  // Wait until we are finished with the jobs
      timer.Stop();

      Console.WriteLine( String.Format( "\n * Tasks required {0} ms for {1} jobs. ", timer.ElapsedMilliseconds, jobBlockCount ) );

    }</pre>
<p>This is the main body of our example where two queues are setup to pass data structures between the three tasks, <code>GPUFFTWorker(), CPUWorker(), &amp; CPUDataReader()</code>. The data stored in the queues are <code>FloatComplexMatrix</code> but it could be any type or data structure as needed. Here our main GPU task is computing a series or 2D FFT&#8217;s, so 2D arrays are passed in the queues. Once the three tasks are started, we simply wait for the main CPU task to finish with all of the analysis, print a message and exit.</p>
<p>The three worker tasks are simple routines which are polling the queues for incoming work, and once their 10 jobs have been completed they exit. The code is provided at the bottom of this article.</p>
<h2>Measuring the offloading</h2>
<p>Running this example as show above, computing 10 3000&#215;3000 2D FFT&#8217;s, we see the following output.</p>
<pre class="code">Enqueued data for job #10 
  Finished FFT on GPU for job 10.
  Dequeued spectrum 10 for analysis 
Enqueued data for job #9 
  Finished FFT on GPU for job 9.
  Dequeued spectrum 9 for analysis 
Enqueued data for job #8 
  Finished FFT on GPU for job 8.
  Dequeued spectrum 8 for analysis 
Enqueued data for job #7 
  Finished FFT on GPU for job 7.
Enqueued data for job #6 
  Dequeued spectrum 7 for analysis 
  Finished FFT on GPU for job 6.
Enqueued data for job #5 
  Finished FFT on GPU for job 5.
  Dequeued spectrum 6 for analysis 
Enqueued data for job #4 
  Finished FFT on GPU for job 4.
  Dequeued spectrum 5 for analysis 
Enqueued data for job #3 
  Finished FFT on GPU for job 3.
Enqueued data for job #2 
  Finished FFT on GPU for job 2.
  Dequeued spectrum 4 for analysis 
Enqueued data for job #1 
 * Finished loading all requested datasets.
  Finished FFT on GPU for job 1.
 * Finished all 2D FFT's.
  Dequeued spectrum 3 for analysis 
  Dequeued spectrum 2 for analysis 
  Dequeued spectrum 1 for analysis 

 * Tasks required 14148 ms for 10 jobs.</pre>
<p>This output shows that the three tasks are indeed running asynchronously and that the final analysis in the <code>CPUWorker</code> can&#8217;t quite keep up with the other two upstream tasks. To measure how much work we are offloading to the GPU, we need to run this example while doing the 2D FFT&#8217;s on the GPU then on the CPU and compare the CPU spark charts in the resource monitor. If we are successfully off loading work to the GPU we should see substantially lower CPU loading while using the GPU for the 2D FFT&#8217;s. We can control the flow of computation by including or commenting out the first line of code in our example.</p>
<pre lang="csharp">//NMathConfiguration.ProcessorSharingMethod = ProcessorManagement.CPU;</pre>
<p>If this line of code is commented out the default processor sharing method of <code>ProblemSize</code> is used which will cause our large 2D FFT&#8217;s to be shunted over to the GPU. If this line is included all processing will be done on the CPU alone.</p>
<p>The following two images were plucked from my resource monitor after a complete run of 30 2D FFT jobs.</p>
<p>Offloading measurement by monitoring CPU loading</p>
<table border="1">
<thead></thead>
<tbody>
<tr>
<td>
<p><figure id="attachment_4509" aria-describedby="caption-attachment-4509" style="width: 196px" class="wp-caption alignnone"><a href="https://www.centerspace.net/blog/wp-content/uploads/2013/06/CPU-Load.png"><img decoding="async" loading="lazy" class="size-full wp-image-4509" alt="CPU load while running FFT's on CPU" src="https://www.centerspace.net/blog/wp-content/uploads/2013/06/CPU-Load.png" width="196" height="466" srcset="https://www.centerspace.net/wp-content/uploads/2013/06/CPU-Load.png 196w, https://www.centerspace.net/wp-content/uploads/2013/06/CPU-Load-126x300.png 126w" sizes="(max-width: 196px) 100vw, 196px" /></a><figcaption id="caption-attachment-4509" class="wp-caption-text">CPU load while running FFT&#8217;s on CPU</figcaption></figure></td>
<td>
<p><figure id="attachment_4510" aria-describedby="caption-attachment-4510" style="width: 197px" class="wp-caption alignnone"><a href="https://www.centerspace.net/blog/wp-content/uploads/2013/06/GPU-Load.png"><img decoding="async" loading="lazy" class="size-full wp-image-4510" alt="CPU load while running FFT's on GPU" src="https://www.centerspace.net/blog/wp-content/uploads/2013/06/GPU-Load.png" width="197" height="466" /></a><figcaption id="caption-attachment-4510" class="wp-caption-text">CPU load while running FFT&#8217;s on GPU</figcaption></figure></td>
</tr>
</tbody>
</table>
<p>I ran these two experiments on my 4-core hyper-threaded i7 desktop using a NVIDIA GeForce 640 GPU. This particular GPU was shipped standard with my Dell computer and would be commonly found in many performance desktops. Clearly shifting the 2D FFT&#8217;s to the GPU offloads a lot of work from my CPU&#8217;s, and in fact CPU-7 and CPU-4 are completely parked (shut down) during the entire run and CPU-3 barely lifted a finger. Now we should go to work on threading the CPU-analysis portion of our code to leverage these idle cores.</p>
<p>&#8211; Happy Computing,</p>
<p>Paul</p>
<h3>Worker Code</h3>
<pre lang="csharp">    // CPUDataReader is responsible gathering the data
    private void CPUDataReader( int jobCounter, Queue dataIn )
    {

      while ( jobCounter &gt; 0 )
      {
        // Read the initial data set from disk and load into memory for
        // each job.  I'm just simulating this with a random matrix.
        FloatComplexMatrix data = new FloatComplexMatrix( 3000, 3000, 
          new RandGenNormal( 0.0, 1.0, 445 + jobCounter ) );

        dataIn.Enqueue( data );

        Console.WriteLine( String.Format( "Enqueued data for job #{0} ", jobCounter ) );

        jobCounter--;
      }

      Console.WriteLine( " * Finished loading all requested datasets." );
    }

    // GPUFFTWorker is responsible for computing the stream of 2D FFT's
    private void GPUFFTWorker( int jobCounter, FloatComplexForward2DFFT fftEngine,   
      Queue dataIn, Queue dataOut )
    {
      FloatComplexMatrix signal;

      // Monitor the job queue and execute the FFT's as the data becomes available.
      while ( jobCounter &gt; 0 )
      {
        if( dataIn.Count &gt; 0 )
        {
          signal = dataIn.Dequeue();

          fftEngine.FFTInPlace( signal );

          Console.WriteLine( String.Format("  Finished FFT on GPU for job {0}.", jobCounter) );

          dataOut.Enqueue( signal );

          jobCounter--;
        }
      }

      Console.WriteLine( " * Finished all 2D FFT's." );
    }

    // CPUWorker is responsible for the post analysis of the data.
    private void CPUWorker( int jobCounter, Queue dataOut )
    {

      while ( jobCounter &gt; 0 )
      {
        if ( dataOut.Count &gt; 0 )
        {

          FloatComplexMatrix fftSpectrum = dataOut.Dequeue();

          Console.WriteLine( String.Format( "  Dequeued spectrum {0} for analysis ", jobCounter ) );

          // Compute magnitude of FFT
          FloatMatrix absFFT = NMathFunctions.Abs( fftSpectrum );

          // Find spectral peaks, write out results, ...

          jobCounter--;
        }
      }
    }</pre>
<p>The post <a rel="nofollow" href="https://www.centerspace.net/offloading-computation-to-your-gpu">Offloading Computation to your GPU</a> appeared first on <a rel="nofollow" href="https://www.centerspace.net">CenterSpace</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.centerspace.net/offloading-computation-to-your-gpu/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4473</post-id>	</item>
		<item>
		<title>NMath Premium Tuning</title>
		<link>https://www.centerspace.net/nmath-premium-tuning</link>
					<comments>https://www.centerspace.net/nmath-premium-tuning#respond</comments>
		
		<dc:creator><![CDATA[Paul Shirkey]]></dc:creator>
		<pubDate>Fri, 31 May 2013 15:49:21 +0000</pubDate>
				<category><![CDATA[NMath Premium]]></category>
		<category><![CDATA[C# GPU]]></category>
		<category><![CDATA[C# Nvidia GPU]]></category>
		<category><![CDATA[NMath GPU]]></category>
		<guid isPermaLink="false">http://www.centerspace.net/blog/?p=4310</guid>

					<description><![CDATA[<p>NMath Premium is designed to be a near drop-in replacement for NMath. However, there are a few important configuration differences and additional logging capabilities that are specific to the premium product.</p>
<p>The post <a rel="nofollow" href="https://www.centerspace.net/nmath-premium-tuning">NMath Premium Tuning</a> appeared first on <a rel="nofollow" href="https://www.centerspace.net">CenterSpace</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><strong>NMath Premium</strong> is the new CenterSpace GPU-accelerated math and statistics library for the .NET platform. The supported NVIDIA GPU routines include both a range of dense linear algebra algorithms and 1D &amp; 2D Fast Fourier Transforms (FFTs). <strong>NMath Premium</strong> is designed to be a near drop-in replacement for <strong>NMath</strong>, however there are a few important configuration differences and additional logging capabilities that are specific to the premium product that I will discuss in this article.</p>
<p><strong>NMath Premium</strong> will be released June 11. For immediate access, sign up <a href="https://www.centerspace.net/nmath-premium/">here</a> to join the beta program.</p>
<h2>Crossover Thresholds</h2>
<p><strong>NMath Premium</strong> makes it very easy to take advantage of the GPU&#8217;s performance benefits by hiding the complexities of data formatting, GPU memory management, algorithms, and diagnostics. Because there is a memory transfer overhead for any type of GPU computation <strong>NMath</strong> automatically routes computations between the CPU and GPU as appropriate for best performance. Additionally there are configuration options that can globally force all computations (regardless of problem size) to either the CPU or GPU. This can be useful for debugging or performance profiling. Let&#8217;s continue with an example.</p>
<pre lang="csharp">   NMathConfiguration.ProcessorSharingMethod = ProcessorManagement.ProblemSize;

   FloatComplexForward1DFFT fft = new FloatComplexForward1DFFT( 1024*1024 );
   FloatComplexVector signal = new FloatComplexVector( 1024*1024, new RandGenUniform( -1, 1, seed) );

   fft.FFTInPlace( signal ); // Execute the million point FFT</pre>
<p>The first line directs <strong>NMath Premium</strong> to route GPU-enabled routines automatically between the CPU and GPU dependent on problem size. Small problems remain on the CPU and large problems are off-loaded to the GPU. The <code>ProblemSize</code> setting is the default behavior and this line of code is not strictly required. The last three lines of code which build the FFT object, populate the random signal vector, and execute the million-point FFT are standard <strong>NMath</strong> code.<em> Except for configuration options, the <strong>NMath Premium</strong> API is unchanged from <strong>NMath</strong>.</em></p>
<p>The problem-size cross-over thresholds can be tuned to control the threshold for every GPU-enabled algorithm. The optimal cross-over threshold is primarily dependent on the computational precision of the problem (<code>Double</code> or <code>Float</code>) and the installed hardware. Frequently applications need to solve similarly sized problems repeatably and the threshold can be adjusted to place the computation where needed. As a default, 1D FFT&#8217;s with a length over 16384 execute on the GPU and 2D FFT&#8217;s with a size larger than 256*256.</p>
<p>The cross-over threshold for any GPU-enabled algorithm can be set with the following code.</p>
<pre lang="csharp">NMathConfiguration.SetCrossoverThreshold( 
   NMathConfiguration.GraphicsProcessorFunctions.FFT1D, 2000);
   ... 
// Now execute a 1D FFT on a 2100 point signal on the GPU.
fft = new FloatComplexForward1DFFT( 2100 );
signal = new FloatComplexVector( 2100, new RandGenUniform( -1, 1, seed) );
fft.FFTInPlace( signal ); // Execute the 2100 point FFT</pre>
<p>With this setting all (complex) 1D FFT&#8217;s with a length greater that 2000 will execute on the GPU.</p>
<h2>Logging and Troubleshooting</h2>
<p>Because <strong>NMath Premium</strong> automatically falls back to the CPU-execution if there any problems with the installed NVIDIA GPU (or if there isn&#8217;t a NVIDIA GPU installed at all), we often found ourselves wanting to verify that our code was actually executing on the GPU. To verify that our small 2100-point FFT did indeed run on the GPU, we can enable GPU logging, run the example, and then check the log file, <code>NMathConfiguration.log</code>. The log file will reside next to the executable unless the <code>LogLocation</code> property has been set to a different directory. The following line of code will enable GPU logging.</p>
<pre lang="csharp">NMathConfiguration.EnableGPULogging = true;</pre>
<p>Logging should only be used while debugging and must be turned on before any <strong>NMath</strong> classes are created. In the current release of <strong>NMath Premium</strong> logging cannot be dynamically turned on or off, but this will change in the future to allow specific sections of code to create log entries. Currently, either the entire program is logging or the entire program is not logging.</p>
<p>Running our 2100-point FFT above we will see the following entries near the end of the log file (many lines have been trimmed from the head of the log file for clarity here).</p>
<pre class="code">   ...
Instantiating GPUManagerKernel: class CenterSpace.NMath.Kernel.GPUKern....

GPU Kernel: GeForce GT 525M CUDA hardware installed and ready to use by NMath Premium.
GPU Kernel: CUDA Driver Version 5.0 detected.
GPU Kernel: CUDA Runtime Version 5.0 detected.

Instantiating FFTManagerKernelGPU: class CenterSpace.NMath.Kernel.FFTMan....
<strong>NMath created GPU executing 1-D, FLOAT REAL, 2100-point FFT object.</strong>
Instantiating FFTKernelInstantiator: class CenterSpace.NMath.Kernel.FF.....</pre>
<p>The bold face line (bold added) reports that we have successfully created a FFT object that will execute its 2100-point FFT&#8217;s on the GPU. Every time such an GPU-active FFT object is created a similar line will be added to this log file. The three lines starting with &#8220;GPU Kernel:&#8221; are reporting the type of GPU hardware found and that the correct NVIDIA CUDA driver and runtime have been detected. If any hardware or driver configuration problems are detected, preventing <strong>NMath Premium</strong> from using the GPU, the various errors will be reported in this section of the log file. Further, additional GPU hardware and driver setup information can be found by running a diagnostic program, deviceQuery.exe, bundled with <strong>NMath Premium</strong> (found in the Assemblies/x64 and Assemblies/x86 directories).</p>
<h2>Summary</h2>
<p>With a few of lines of code .NET developers can now write optimally executing GPU software with <strong>NMath Premium</strong>. Applications currently using <strong>NMath</strong> can easily be accelerated by installing <strong>NMath Premium</strong> with few if any code changes. Small problems remain on the CPU and large problems are routed to the GPU and the programmer has control over the cross-over thresholds for all GPU-enabled classes in <strong>NMath Premium</strong>. A logging capability is provided to help with any GPU hardware or driver issues and to verify that your FFT&#8217;s are executing on the installed NVIDIA GPU.</p>
<p>For more information on <strong>NMath Premium</strong> tuning, see the chapter on NMath Premium in the <em>NMath User&#8217;s Guide</em>.</p>
<p>Happy Computing,</p>
<p>-Paul Shirkey</p>
<p>The post <a rel="nofollow" href="https://www.centerspace.net/nmath-premium-tuning">NMath Premium Tuning</a> appeared first on <a rel="nofollow" href="https://www.centerspace.net">CenterSpace</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.centerspace.net/nmath-premium-tuning/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4310</post-id>	</item>
		<item>
		<title>NMath Premium: FFT Performance</title>
		<link>https://www.centerspace.net/nmath-premium-fft-performance</link>
					<comments>https://www.centerspace.net/nmath-premium-fft-performance#respond</comments>
		
		<dc:creator><![CDATA[Paul Shirkey]]></dc:creator>
		<pubDate>Tue, 28 May 2013 16:00:29 +0000</pubDate>
				<category><![CDATA[NMath Premium]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[C# GPU]]></category>
		<category><![CDATA[C# Nvidia GPU]]></category>
		<category><![CDATA[GPU]]></category>
		<guid isPermaLink="false">http://www.centerspace.net/blog/?p=4212</guid>

					<description><![CDATA[<p><img class="excerpt" title="Double Precision FFT" src="https://www.centerspace.net/blog/wp-content/uploads/2013/02/ScreenClip-51.png" alt="NMath Premium" /><br />
NMath Premium is CenterSpace Software's NVIDIA GPU-accelerated edition of the NMath math and statistics library. Many linear algebra and signal processing algorithms can now run on a local NVIDIA GPU processor, frequently realizing several multiples of performance gain. In this post, we look at  the performance of complex to complex forward 1D and 2D FFT's.</p>
<p>The post <a rel="nofollow" href="https://www.centerspace.net/nmath-premium-fft-performance">NMath Premium: FFT Performance</a> appeared first on <a rel="nofollow" href="https://www.centerspace.net">CenterSpace</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><strong> NMath Premium </strong> is our new GPU-accelerated math and statistics library for the .NET platform. The supported NVIDIA GPU routines include both a range of dense linear algebra algorithms and 1D and 2D Fast Fourier Transforms (FFTs). NMath Premium is designed to be a near drop-in replacement for NMath, however there are a few important differences and additional logging capabilities that are specific to the premium product.</p>
<p><strong>NMath Premium</strong> will be released June 11. For immediate access, sign up <a href="https://www.centerspace.net/nmath-premium/">here</a> to join the beta program.</p>
<h2>Benchmark Approach</h2>
<p>Modern FFT implementations are hybridized algorithms which switch between algorithmic approaches and processing kernels depending on the available hardware, FFT type, and FFT length. A FFT library may use the straight Cooly-Tukey algorithm for a short power-of-two FFT but switch to Bluestein&#8217;s algorithm for odd-length FFT&#8217;s. Further, depending on the factors of the FFT length different combinations of processing kernels may be used. In other words there is no single &#8216;FFT algorithm&#8217; and so there is no easy expression for FLOPS completed per FFT computed. Therefore, when analyzing the performance of FFT libraries today, the performance is often reported <em> relative to the Cooly-Tukey implementation </em> with the FLOPs estimated at <code> 5 * N * log( N ) </code>. This relative performance is reported here. As an example, if we report a performance of 10 GFLOP&#8217;s for a particular FFT, that means if you ran an implementation of the Cooly-Tukey algorithm you&#8217;d need a 10 GFLOP&#8217;s capable machine to match the performance (finish as quickly).</p>
<p>Because GPU computation takes place in a different memory space from the CPU, all data must be copied to the GPU and the results then copied back to the CPU. This copy time overhead <em>is included in all reported performance numbers.</em> We include this copy time to give our library users an accurate picture of attainable performance.</p>
<h3>GPU&#8217;s Tested</h3>
<p>The <strong> NMath Premium </strong> 1D and 2D FFT library was tested on four different NVIDIA GPU&#8217;s and a 4-core 2.0Ghz Intel i7. These models represent the current range of performance available from NVIDIA, ranging from the widely installed GeForce GTX 525 to NVIDIA&#8217;s fasted double precision GPU, the Tesla K20.</p>
<table>
<tbody>
<tr>
<th>GPU</th>
<th>Peak GFLOP (single / double)</th>
<th>Summary</th>
</tr>
<tr>
<td>Tesla K20</td>
<td>3510 / 1170</td>
<td>Optimized for applications requiring double precision performance such as computational physics, biochemistry simulations, and computational finance.</td>
</tr>
<tr>
<td>Tesla K10</td>
<td>2288/ 95</td>
<td>This is a dual GPU processor card optimized for single precision performance for applications such as seismic and video or image processing. If both GPU cores are maximally utilized these GFLOP numbers would double.</td>
</tr>
<tr>
<td>Tesla 2090</td>
<td>1331/ 655</td>
<td>A single core GPU with a more balanced single and double precision performance.</td>
</tr>
<tr>
<td>GeForce 525</td>
<td>230 / &#8211;</td>
<td>A single core consumer GPU found in many gaming computers.</td>
</tr>
</tbody>
</table>
<h2>FFT Performance Charts</h2>
<p>The four charts below represent the performance of various power-of-two length, complex to complex forward 1D and 2D FFT&#8217;s. All <strong>NMath </strong>products also seamlessly compute non-power-of-two length FFT&#8217;s but their performance is not part of this GPU comparison note.</p>
<p>The performance of the CPU-bound 1D FFT outperformed all of the GPU&#8217;s for relatively short FFT lengths. This is expected because the superior performance of the GPU&#8217;s cannot be enjoyed due to the data transfer overhead. Once the computational complexity of the 1D FFT is high enough the data transfer overhead is outweighed by the efficient parallel nature of the GPU&#8217;s, and they start to overtake the CPU-bound 1D FFT&#8217;s. This cross-over point occurs when the FFT reaches a length near 65536. The exception is the consumer level GeForce GTX 525, where the GPU and CPU FFT performance roughly track each other.</p>
<p>The 2D FFT case is different because of the higher computational demand of the two-dimensional case. First, in the single precision case we see the inferiority of the NVIDIA K20, which is designed primarily as a double precision computation engine. Here the CPU-bound outperforms the K20 for all image sizes. However the K10 and 2090 are extremely fast (including the data transfer time) and outperform the CPU-bound 2D FFT by approximately 60-70%. In the double precision 2D FFT case, the K20 outperforms all other processors in nearly all cases measured. The tested K20 was memory limited in the [ 8192 x 8192 ] test case and couldn&#8217;t complete the computation.</p>
<table>
<tbody>
<tr>
<td><a href="https://www.centerspace.net/blog/wp-content/uploads/2013/02/ScreenClip-61.png"><img decoding="async" title="Performance of single precision FFT" alt="" src="https://www.centerspace.net/blog/wp-content/uploads/2013/02/ScreenClip-61.png" width="350 class=" /></a></td>
<td><a href="https://www.centerspace.net/blog/wp-content/uploads/2013/02/ScreenClip-51.png"><img decoding="async" title="Performance of double precision FFT" alt="" src="https://www.centerspace.net/blog/wp-content/uploads/2013/02/ScreenClip-51.png" width="350 class=" /></a></td>
</tr>
<tr>
<td><a href="https://www.centerspace.net/blog/wp-content/uploads/2013/02/ScreenClip-12.png"><img decoding="async" class="alignnone size-full wp-image-4231" title="Performance or single precision 2D FFT" alt="Performance or single precision 2D FFT" src="https://www.centerspace.net/blog/wp-content/uploads/2013/02/ScreenClip-12.png" width="350" srcset="https://www.centerspace.net/wp-content/uploads/2013/02/ScreenClip-12.png 800w, https://www.centerspace.net/wp-content/uploads/2013/02/ScreenClip-12-300x262.png 300w" sizes="(max-width: 800px) 100vw, 800px" /></a></td>
<td><a href="https://www.centerspace.net/blog/wp-content/uploads/2013/02/ScreenClip-13.png"><img decoding="async" class="alignnone size-full wp-image-4232" title="Performance of double precision 2D FFT" alt="Performance of double precision 2D FFT" src="https://www.centerspace.net/blog/wp-content/uploads/2013/02/ScreenClip-13.png" width="350" srcset="https://www.centerspace.net/wp-content/uploads/2013/02/ScreenClip-13.png 800w, https://www.centerspace.net/wp-content/uploads/2013/02/ScreenClip-13-300x262.png 300w" sizes="(max-width: 800px) 100vw, 800px" /></a></td>
</tr>
</tbody>
</table>
<h3>Batch FFT</h3>
<p>To amortized the cost of data transfer to and from the GPU, <strong> NMath Premium </strong> can run FFT&#8217;s in batches of signal arrays. For the smaller FFT sizes, the batch processing nearly doubles the performance of the FFT on the GPU. As the length of the FFT increases the advantage of batch processing decreased because the full array signals can no longer be loaded into the GPU.</p>
<p><a href="https://www.centerspace.net/blog/wp-content/uploads/2013/02/BatchFFT.png"><img decoding="async" class="alignnone size-full wp-image-4259" title="Performance of batch 1D FFT" alt="" src="https://www.centerspace.net/blog/wp-content/uploads/2013/02/BatchFFT.png" width="350" srcset="https://www.centerspace.net/wp-content/uploads/2013/02/BatchFFT.png 800w, https://www.centerspace.net/wp-content/uploads/2013/02/BatchFFT-300x262.png 300w" sizes="(max-width: 800px) 100vw, 800px" /></a></p>
<h2>Summary</h2>
<p>As the complexity of the FFT increases either due to an increase in length or problem dimension the GPU leveraged FFT performance overtakes the CPU-bound version. The advantage of the GPU 1D FFT grows substantially as the FFT length grows beyond ~100,000 samples. Batch processing of signals arranged in rows in a matrix can be used to mitigate the data transfer overhead to the GPU. There are times where it may be advantageous to offload the processing of FFT&#8217;s onto the GPU even when CPU-bound performance is greater because this will free many CPU cycles for other activities. Because <strong> NMath Premium </strong> supports adjustable crossover thresholds the developer can control the FFT length at which FFT computation switchs to the GPU. Setting this threshhold to zero will push all FFT processing to the GPU, completely offloading this work from the CPU.</p>
<p>The post <a rel="nofollow" href="https://www.centerspace.net/nmath-premium-fft-performance">NMath Premium: FFT Performance</a> appeared first on <a rel="nofollow" href="https://www.centerspace.net">CenterSpace</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.centerspace.net/nmath-premium-fft-performance/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4212</post-id>	</item>
	</channel>
</rss>
