January 22, 2009

Microsoft Accelerator (GPU) based Pi Calculation - A C# Port



This is a quick and dirty port.
Microsoft Research Accelerator Project


using
System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Research.DataParallelArrays;

namespace piSharp.cs
{
class Program
{
static void Main(string[] args)
{
Random r =
new Random();
// create randomly generated samples in the unit square centered on (0,0)

int iSize = 1500;
float[,] x = new float[iSize + 1, iSize + 1];
// x coordinate
float[,] y = new float[iSize + 1, iSize + 1];
// y coordinate
int i = 0;
int j = 0;

// create an x and y arrays of random numbers between 0 and 1
for (i = 0; i <= iSize - 1; i += 1) { for (j = 0; j <= iSize - 1; j += 1) { x[i, j] = (float)r.NextDouble();
y[i, j] = (
float)r.NextDouble();
}
}
ParallelArrays.InitGPU();

// make x and y data parallel arrays
DisposableFloatParallelArray parallelX =
new DisposableFloatParallelArray(x);
DisposableFloatParallelArray parallelY =
new DisposableFloatParallelArray(y);

// center them about (0, 0) with range (-1, 1)
FloatParallelArray parallelXCentered =
default(FloatParallelArray);
FloatParallelArray parallelYCentered =
default(FloatParallelArray);
parallelXCentered = ParallelArrays.Multiply(ParallelArrays.Subtract(parallelX, 0.5f), 2f);
parallelYCentered = ParallelArrays.Multiply(ParallelArrays.Subtract(parallelY, 0.5f), 2f);

// calculate distance of (x,y) from 0, ie. Sqrt(x^2 + y^2)
FloatParallelArray parallelXSquare =
default(FloatParallelArray);
FloatParallelArray parallelYSquare =
default(FloatParallelArray);
FloatParallelArray parallelDistance =
default(FloatParallelArray);
parallelXSquare = ParallelArrays.Multiply(parallelXCentered, parallelXCentered);
parallelYSquare = ParallelArrays.Multiply(parallelYCentered, parallelYCentered);
parallelDistance = ParallelArrays.Sqrt(ParallelArrays.Add(parallelXSquare, parallelYSquare));
float[,] test = new float[iSize + 1, iSize + 1];
ParallelArrays.ToArray(parallelDistance,
out test);

// create an array of 1's if distance <> 1
FloatParallelArray parallelOne =
new FloatParallelArray(1f, parallelX.Shape);
FloatParallelArray parallelZero =
new FloatParallelArray(0f, parallelX.Shape);
FloatParallelArray parallelInCircle =
default(FloatParallelArray);

parallelInCircle = ParallelArrays.Select(ParallelArrays.Subtract(parallelOne, parallelDistance), parallelOne, parallelZero);

// the number inside the circle is the sum of the entire InCircle array
FloatParallelArray parallelCountInCircle =
default(FloatParallelArray);
parallelCountInCircle = ParallelArrays.Sum(parallelInCircle);

float[] inCircle = new float[2];
ParallelArrays.ToArray(parallelCountInCircle,
out inCircle);
parallelX.Dispose();
parallelY.Dispose();

// approximate pi--area of unit circle is pi
// area of square from -1,1 is 4
// inCircle/(total number of points) == pi/4
float pi = 0;
pi = 4 * inCircle[0] / (iSize * iSize);
System.Console.WriteLine(
"Pi is approximately " + pi.ToString());
ParallelArrays.UnInit();

// Prompt user for exit for running in VS IDE
System.Console.WriteLine(
"Press Enter to Exit");
System.Console.ReadLine();
}
}
}


Back to Home

1 comments:

Bart van der Werf (Bluelive) said...

Thanks, i used this example while debugging my own accelerator using program.
Get lost with asking the .ToArray with a wrong dimensional array. (gives great native errors in c# :)

Post a Comment