Idiot's Guide to Grid Computing - Part I






4.29/5 (9 votes)
How to use grid computing with Alchemi.
Introduction
Recently, I needed to do a lot of computing in a relatively short period of time, so I looked on Sourceforge.net for distributed computing. I found Alchemi, a .NET library used to implement grid computing.
Background
What is grid computing? Grid computing is the distribution of threads across a network or the Internet. A grid consists of a computer requesting threads to be executed (called the owner), a manager which sends the threads to computers who will execute them, and executors which execute the thread(s) assigned to them. Then, the results of the threads are sent back to the owner through the manager.
Using the Code
Alchemi makes grid computing quite easy to implement, using inherited classes and an application object.
The basic form of an application is like this:
using System;
using Alchemi.Core;
using Alchemi.Core.Owner;
namespace UselessApp
{
[Serializable]
public class MyThread : GThread
{
public override void Start()
{
}
}
class MultiplierApplication
{
static GApplication ga; [STAThread]
static void Main(string[] args)
{
// create grid application
ga = new GApplication(new GConnection("localhost",
9000, "user", "user"));
// tell the program to send itself over network
ga.Manifest.Add(new ModuleDependency(typeof(MyThread).Module));
//create thread
MyThread thread = new MyThread();
// add thread to application
ga.Threads.Add(thread);
// start application
ga.Start();
}
}
}
This would send the program over the network to an executor, then run the thread. The thread does nothing, so the program just shuts down. Before you run the code, you will need Alchemi. To get Alchemi, go here. You will need the manager and executor installers. After you install the manager and executor, you will need to reference the libraries, which are wherever you installed the manager and the executor (both locations). In order to run the useless application, you will need to start the manager and executor. Go to Start->Programs ->Alchemi, then into Manager or Executor, respectively. The default settings for the executor and manager will work. The basic application should compile and run now. Now, on to something more useful: GUID generation and comparing them to see if there are duplicates.
The Useful Application
Currently, you have the framework for an application that is completely useless. Let's expand on it by generating 300 GUIDs and comparing them (that was my Science project). First, let's add a constructor to the thread class. The class should look like this:
[Serializable]
public class MultiplierThread : GThread
{
private String current;
private String[] guids = new String[300];
private int num=0;
private bool already = false;
int mystart, myend;
public int Result
{
get
{
return num;
}
}
public MultiplierThread(int start, int end, String[] guid)
{
mystart = start;
myend = end;
guids = guid;
}
~MultiplierThread()
{
guids = null;
}
public override void Start()
{
for (int i = mystart; i < myend; i++)
{
current = guids[i];
for (int n = 0; n < 300; n++)
{
if(current==guids[n])
{
if(already) num++;
else already=true;
}
already=false;
}
}
}
}
Next, we'll modify the application class to create the threads and add some variables. We will also add event handlers for the completion of the threads and the application. The class should look like this:
class MultiplierApplication
{
static GApplication ga;
static int num;
[STAThread]
static void Main(string[] args)
{
// create grid application
GConnectionDialog conndia = new GConnectionDialog();
if (conndia.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
ga = new GApplication(conndia.Connection);
}
else
{
Console.WriteLine("A connection must be created.");
return;
}
// add GridThread module (this executable) as a dependency
ga.Manifest.Add(new ModuleDependency(typeof(MultiplierThread).Module));
String[] guids = new String[300];
for (int i = 0; i < 300; i++)
{
guids[i] = Guid.NewGuid().ToString();
}
// create and add 300 threads to the application
for (int i = 0; i < 300; i++)
{
// create thread
MultiplierThread thread = new MultiplierThread(i, i+1, guids);
// add thread to application
ga.Threads.Add(thread); }
// subscribe to events
ga.ThreadFinish += new GThreadFinish(ThreadFinished);
ga.ThreadFailed += new GThreadFailed(ThreadFailed);
ga.ApplicationFinish += new GApplicationFinish(ApplicationFinished);
// start application
ga.Start();
}
}
static void ThreadFinished(GThread th)
{
// cast GThread back to MultiplierThread
MultiplierThread thread = (MultiplierThread) th;
Console.WriteLine( "thread # {0} finished with" +
" result '{1}'", thread.Id, thread.Result);
num = num + thread.Result;
GC.Collect(GC.GetGeneration(thread));
GC.Collect(GC.GetGeneration(th));
}
static void ThreadFailed(GThread th, Exception e)
{
Console.WriteLine( "thread # {0} finished with" +
" error '{1}'", th.Id, e.Message);
GC.Collect(GC.GetGeneration(th));
}
static void ApplicationFinished()
{
StreamWriter sw;
sw = new StreamWriter("results.txt");
sw.WriteLine();
sw.Write("Number of ambiguous GUIDs for " +
"the Microsoft .Net algorithm: ");
Console.Write("Number of ambiguous GUIDs " +
"for the Microsoft .Net algorithm: ");
sw.Write(num.ToString());
sw.Close();
}
}
Don't forget the using
statements (for I/O):
using System;
using Alchemi.Core;
using Alchemi.Core.Owner;
using System.IO;
This will generate 300 GUIDs and compare them to each other. There is still room for improvement though, so let's add a connection dialog to the application. The connection dialog will allow the user to connect to a manager other than the owner. A connection dialog is supplied with the library, so we only need to change
ga = new GApplication(new GConnection("localhost", 9000, "user", "user"));
to
// create grid application
GConnectionDialog conndia = new GConnectionDialog();
if (conndia.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
ga = new GApplication(conndia.Connection);
}
else
{
Console.WriteLine("A connection must be created.");
return;
}
which will make a dialog pop up, requesting information for the connection.
Conclusion
Now that you know the basics of using Alchemi, you can do a lot more with multithreading. In my next installation of the Idiot's Guide to Grid Computing, I will show you how to use Alchemi with Managed C++.
Points of Interest
You can send all dependencies over the network using the manifest
property of the Application
class.
This application requires three dependencies (System
, System.Windows.Forms
, Alchemi.Core)
and one source file.
History
- Completed and uploaded tutorial at 7:01 PM on 11/24/06.
- Updated on 06/04/07 at 1:31 PM.