 |
|
A quick example about how to submit MPI DotNET job to Windows cluster RCWINCLU
Intro: Please read "Access windows cluster rcwinclu" and How to submit a job in Windows cluster before proceed.
1> Please download the C# version of "MPI NET" source code and recompile it with MS Visual Studio 2008. If you are inside PHS network, you can go to \\rcwinclu\public\HPCSamples\SplitSearching to download the source. If you do not have Visual Studio 2008, please download the trial or expression version from Microsoft website.
Note: This simple code is to split a relative larger sorting task into many smaller sorting tasks, then use binary search algorithm to identify repeat items in master node quickly. You can certainly improve the performance in many ways if you are interested in making it more efficient. Basically, this code will do the following:
a) The master node (root node assigned by MPI, can be a computing core) generates a large random integer array.
b) The master split the array into #number of smaller arrays and distributes them into #number of child node (can be computing cores).
c) Each child sorts its own array.
d) The master broadcasts its own subset to each child for comparison.
e) Each child compare its own array with the array received from the master node, find the repeated item and print them out.
Note: If you want to compile it in your own environment instead of in HPCWIN, You might need to download MS MPI.NET and then make reference to the Microsoft Message Passing Interface (MPI.dll). More docs please visit \\rcwinclu\public\windowsHPC_doc
2> Here is the source code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MPI;
using System.Security.Principal;
namespace SplitSearching
{
class Program
{
static void Main(string[] args)
{
using (new MPI.Environment(ref args))
{
int i, j;
String filepath;
int MyArraySize = 10000;
int ComparingArraySize = 500;
int SubArraySize = 0;
string filename = "";
filepath = UtilFunc.getCurrentPath();
int rank = Communicator.world.Rank;
Communicator comm = Communicator.world;
SubArraySize = MyArraySize / comm.Size;
int[] SubArray = new int[SubArraySize];
int[] ComparingArray = new int[ComparingArraySize];
if (rank == 0)
{
int[] MyLargeArray = UtilFunc.GetRandomArray(MyArraySize);
ComparingArray = UtilFunc.GetRandomArray(ComparingArraySize);
for (i = 0; i < comm.Size; i++)
{
for (j = 0; j < SubArraySize; j++)
{
SubArray[j] = MyLargeArray[i * SubArraySize + j];
}
if (i > 0)
{
comm.Send(SubArray, i, 0);
}
}
filename = "Original";
UtilFunc.writetoFile(filepath, filename, rank, MyLargeArray);
filename = "Splitted";
Array.Sort(SubArray);
UtilFunc.writetoFile(filepath, filename, rank, SubArray);
}
else
{
comm.Receive(0, 0, ref SubArray);
filename = "Splitted";
Array.Sort(SubArray);
UtilFunc.writetoFile(filepath, filename, rank, SubArray);
}
comm.Broadcast(ref ComparingArray, 0);
filename = "Comparing";
UtilFunc.writetoFile(filepath, filename, rank, ComparingArray);
UtilFunc.ComparingTwoArrays(SubArray, ComparingArray, rank);
}
}
}
}
Here is the UtilFunc class being used by the main program
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Principal;
namespace SplitSearching
{
static class UtilFunc
{
public static String getIdent()
{
String userid = "";
userid = WindowsIdentity.GetCurrent().Name;
string subSt = "";
int pos = userid.LastIndexOf(Convert.ToChar(@"\"));
if ((pos >= 0))
{
subSt = userid.Substring((pos + 1));
}
return subSt;
}
public static String getCurrentPath()
{
return Directory.GetCurrentDirectory();
}
public static int[] GetRandomArray(int ArrayLen)
{
int[] myarray = new int[ArrayLen];
int i;
DateTime x = DateTime.Now;
float mins = x.Minute;
float secs = x.Second;
float hour = x.Hour;
Random random = new Random(Convert.ToInt32((secs * mins) + hour));
for (i = 0; i < ArrayLen; i++)
{
myarray[i] = random.Next(ArrayLen);
}
return myarray;
}
public static void writetoFile(string FilePath, string FileName, int CompCoreID, int[] TmpArray)
{
FileName = FilePath + @"\" + FileName + "output" + "_" + Convert.ToString(CompCoreID) + ".txt";
TextWriter tw = new StreamWriter(FileName);
int j = 0;
for (j = 0; j < TmpArray.Length; j++)
{
tw.WriteLine(TmpArray[j]);
}
tw.Close();
}
public static void ComparingTwoArrays(int[] Arr1, int[] Arr2, int CompCoreID)
{
int i;
for (i = 0; i < Arr1.Length; i++)
{
if (BinarySearch(Arr1[i], Arr2) == 1)
{
System.Console.Out.WriteLine("Found matches at Core " + CompCoreID + " for value " + Convert.ToString(Arr1[i]));
}
}
}
public static int BinarySearch(int SearchNum, int[] TmpArray)
{
int LowNum = 0;
int SizeNum = TmpArray.Length;
//get the high number in the array
int HighNum = SizeNum - 1;
//loop while the low number is less or equal to the high number
while (LowNum <= HighNum)
{
//get the middle point in the array
int MidNum = (LowNum + HighNum) / 2;
//now start checking the values
if (SearchNum < TmpArray[MidNum])
{
//search value is lower than this index of our array
//so set the high number equal to the middle number
//minus 1
HighNum = MidNum - 1;
}
else if (SearchNum > TmpArray[MidNum])
{
//search value is higher than this index of our array
//so set the low number to the middle number + 1
LowNum = MidNum + 1;
}
else if (SearchNum == TmpArray[MidNum])
{
return 1;
}
}
return 0;
}
}
}
2> Compile this program, upload the executable file SplitSearching.exe into \\rcwinclu\PARTNERSID (Note: $PARTNERID is your own Partners ID).
3> Start your "HPC Job Manager" from your client.
4> Leave the Job Detail as default, and configure the Task Detail as following.
here is the GUI for "Task Detail"
5> Fill in the following fields:
a. TaskName --> MyTestMPIC
b. CommandLine --> "mpiexec -n 10 SplitSearching.exe " (Note: "mpiexec" is the MPI job launcher ( and you need to use it for all MPI .Net application , "-n 10" means you will allocate 32 computing coreS, "mpiintegral" is the example application).
c. Working Directory --> "\\rcwinlu\$PARTNERSID (Note: here we use "testy" as example, you need to change it).
d. Standard Output --> "std.out"
e. Standard Error --> "std.err"
f. Minimum and Maximum number of cores are same as in command line.
6> Submit the job
|