Sunday, September 28, 2008

24-Core Linux Cluster in a $29.99 Case from IKEA

Update: Why Would Anyone Need a Computer Cluster?

For many applications such as real-time stock prediction algorithms or brain simulations, there is a need for extremely fast and massively parallel computing. My friend, Alex Nugent, and I needed some enormous computational power for some projects we are working on and wanted a cheap and elegant solution. We already built a handful of dual-core headless Linux boxes and added them to our local network, but we could see that adding more would not go too far because of space limitations. What we needed was a compact and efficient design with maximal core density. Rack mountable servers were quite expensive relative to a hand-built quad-core Linux boxes. We imagined there existed some kind of cabinet that would be perfect for housing a bunch of computers. Each host in the cluster would consist of the bare minimal of components for our applications with a main emphasis on fast processing and less on RAM and hard drive capacity. The enclosures for each host would have to hold a motherboard, power supply, RAM, CPU w/ fan, and hard drive.





I looked around on the Ikea website and after an hour, I pared down all possible furniture pieces to Helmer. About five minutes later, I checked out Digg, and the third story from the top was coincidentally about a guy in Sweden who built a Linux cluster into a Helmer cabinet. The very next day I received an IKEA advertisement showing Helmer on sale for only $29.99 from $49.99. At that point, I was sure that the Helmer cabinet was meant to be the future case our our cluster, and I picked it up the next day! The following is an illustrated guide to building your own 24-core Linux cluster in pictures.

Components:
(1) Ikea Helmer Cabinet $29.99
(6) BioStar TForce TA780G M2+ Motherboard $79.99
(6) AMD Phenom X4 9850 Black CPU $169.00
(6) Antec EA380 380 W Power Supply Unit $59.99
(6) Toshiba 80-GB Sata2 Laptop Hard Drive $49.99
(6) G-Skill 1GBX2 DDR2 RAM $42.99
(6) EverCool 50mm Case Fan $3.79
(6) 3-foot LAN Patch Cables $1.49
(1) 8-Plug Surge Protected Power Strip $39.99
(1) TrendNet 8-Port Unmanaged Switch $18.49
(6) Linux Operating Systems $00.00
Misc. Parts $20.00
----------------------------------------------------------
Total $2550.11

Component Layout
We wanted to keep Helmer's drawers as intact as possible in order to maintain a sound and stable finished product. Besides just looking clean and elegant, building each host into a single drawer organizes and modularizes everything nicely for future maintenance. I wonder if the Helmer designer at Ikea made the drawers exactly for this because the components fit inside perfectly without a millimeter to spare in some instances. The power supply, which is a 380 W full size ATX PSU sits flush with the top of the drawer. The micro-ATX mobo (motherboard) fits in the rest of the space with about a millimeter to spare from front to back and about a centimeter on the left side of the drawer. A regular 3.5 inch form factor hard drive won't fit in the remaining space next to the PSU, so we ended up going with a 2.5 inch form factor laptop hard drive. It fits almost perfectly with a few millimeters to spare. The distance from the CPU fan to the bottom of the above drawer is about 2.5 cm. All the cabling fits beautifully after we removed some of the unnecessary power lines from the PSU. Always take Electrostatic Discharge (ESD) precautions when handling any printed circuit boards or raw circuitry.

Case Cooling
Since the PSU fan blows air out the back of the drawer, we designed the rest of the cooling system so that air would move from the front and out the back. We made cutouts for the PSU and an additional 50 mm case fan on the back of the drawer, and we modified the label holder on the front of the draw to let air in. Holes were drilled to attach the PSU to three of the four attachment points and all four attachment points for the case fan. There is enough space between the PSU and the case fan for the LAN patch cable to exit. After a bit of trial and error the easiest way to cut the correct shapes in the back of the drawers is to use a cut-cut-score method. After you have the cutout pattern drawn on the sheet metal, you take a sheet metal snips and make two cuts on two sides of a triangle. For the third side of the triangle, score the metal with a razor blade and bend the metal back and forth along the score line until it snaps off. Repeat that until the entire cutout is achieved. The front air inlet port is very easy to create. Insert a hack saw blade into the label holder on front of the drawer and cut along the bottom edge to the other side. Bend the flap of metal back into the drawer.

Modifications
The power supplies we bought had a lot of extra power wires coming out of it than we needed and they took up valuable cooling space inside the case. We decided to cut all the wires we didn't need and toss them away. After cutting the unnecessary wires, you need to terminate the ends some way. We attached all similar-colored wires together and terminated the end with a wire nut. Make sure to screw the wire nut on very tight and also attach it with some electrical tape so it can't accidentally come off. If for some reason in the future, one of these wires escapes and touches the mobo or the case, the entire cluster could be fried! We also added a push-button power switch to the front of the case. Make sure to get normally-off momentary push button switches. You need to drill a hole for the switch in the front of the drawer, solder a wire to the switch, and attach a Molex connector to the other end of the wire to attach to the on/off jumpers on the mobo. Since the cluster is designed to be headless (no monitor connected, managed remotely), it's OK that it's impossible to connect external hardware to the mobo except for the LAN patch cable. Because of the tight quarters between the LAN port and the side of the drawer, we had to modify the LAN patch cable by removing the plastic cable wrapping directly behind the clear plastic plug with a razor blade so that the actual wires could bend 90 degrees after exiting the connector. Finally, you need to extend the length of the case fan wires using simple crimp-style wire connectors.

Final Steps
Before you put all the computer parts in each drawer case, you need to piece the computer together on a table and modify a few BIOS settings and install an operating system of your choice with an optical drive. Otherwise, after you have all the components in, it is a bit difficult to hook up a monitor, keyboard and mouse to the mobo because of the tight space. We adjusted the BIOS settings to enable the Wake-On-LAN feature, which I blogged about previously here. We installed Xubuntu on each host. While I'm sure there is a different flavor of Linux more appropriate for a headless Linux host, we went with Xubuntu because we're comfortable with it. If you have a suggestion of what OS would be better, please leave a comment. The only constraint is that we need to be able to run a Java program. After you have all the hardware and software modifications complete, put all the components into each drawer and into the Helmer cabinet. Connect each PSU and the router to the power strip and each host to the router. Plug the router into your local area network (LAN) and you have 24 cores more at your service!

While we have not yet quantified how "fast" our cluster is, we have been able to finish our computations roughly 24 times faster than one of our single core computers, which translates to an immense gain in productivity. That means, what would take 24 hours before can be accomplished in one hour. We still want to play around with some over-clocking, and we'll ramp up to that eventually. At idle speed, the CPU temps are are around 30 degrees Celsius. With all 24 cores at 100% load, the CPU temperatures stay at a nice and warm temperature of about 45 degrees Celsius. The air flow through the drawers sufficiently keeps the components cool, and at full tilt, you can feel a strong warm breeze come out of the rear of Helmer.

Other Thoughts
The idea of building a 6-host 24-core cluster in such a small space for such a low price tag of $2550.11 is very attractive not only for specialty applications, but also for businesses or educational departments looking to invest in a handful of servers. With Linux desktop and server operating systems such as Ubuntu forcefully emerging on the scene and taking away market share from Microsoft, people will inevitably embrace these faster, safer, easier and more elegant computing systems. That, in combination with compact, reliable, and inexpensive computer hardware will pave the way to better systems at any scale. I'm guessing that using Helmer cases and quad-core AMD processors, one could build the world's fastest and most efficient super computer at a fraction of the cost of the next fastest. Perhaps a "Helmer" will someday become a unit of measurement defined as "six computers in 2.65 cubic feet" or something like that.

Update: Check out the gallery to the right for pics of putting Helmer together. -------------->


Wednesday, September 24, 2008

Plotting 2-D Surfaces Using Java SWT

If you are creating an RCP application in Eclipse or just using Java's SWT graphics packages for your program, there may be a need to make a surface plot to display some data contained in a matrix. Rather than learning an additional graphics package like Java 2D or JFreeChart, if you're already using SWT as the basis of your application, it's best just stick with that. It's also incredibly easy to do as demonstrated in the code snippet below. The main method creates a Shell which contains the 2-D surface plot. The createContents method creates a Canvas object, and within the PaintListener, it colors each pixel according the matrix returned by getMatrix. The constructor for the Color object takes and RGB value, and you need to be sure that your matrix only includes integers between 0 and 255 or it won't work. The getMatrix method just returns a 2-D matrix of integers. Just for demonstration purposes, I came up with three simple example matrices. The matrix plotted to the left is just random noise scaled between 0 and 255 using matrix[i][j] = (int)(Math.random()*255) in the getMatrix method.




Here's the entire snippet:

package com.timmolter.samples;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class SurfacePlotter {

static int size = 400;

public static void main(String[] args) {

Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Surface Plot using SWT.");
createContents(shell);
shell.setSize(size, size);
shell.open();
while( !shell.isDisposed())
{
if(!display.readAndDispatch())
display.sleep();
}
display.dispose();
}

private static void createContents(final Shell shell) {

// GridLayout for shell
GridLayout gridLayoutMain = new GridLayout();
gridLayoutMain.makeColumnsEqualWidth = true;
shell.setLayout(gridLayoutMain);

// Surface Canvas
final Canvas surfaceCanvas = new Canvas(shell, SWT.NONE);
surfaceCanvas.addPaintListener(new PaintListener(){

public void paintControl(PaintEvent e) {

int[][] matrix = getMatrix(surfaceCanvas.getSize().x, surfaceCanvas.getSize().y);

for(int i=0; i < matrix.length; i++){
for(int j=0; j < matrix[0].length; j++){
e.gc.setForeground(new Color(e.display, matrix[i][j], matrix[i][j], matrix[i][j])); //rgb
e.gc.drawPoint(i, j);
}
}
}
});

// GridData for surfaceCanvas
GridData data = new GridData(GridData.FILL_BOTH);
surfaceCanvas.setLayoutData(data);

}

private static int[][] getMatrix(int xSize, int ySize){

int[][] matrix = new int[xSize][ySize];
for (int i = 0; i < xSize; i++) {
for (int j = 0; j < ySize; j++) {
matrix[i][j] = (int)(Math.random()*255);
//matrix[i][j] = (int)((.5*(Math.sin(j)+1))*255);
//matrix[i][j] = (int)(((.25*(Math.sin(i)+1))+(.25*(Math.cos(j)+1)))*255);
}
}
return matrix;
}
}

matrix[i][j] = (int)((.5*(Math.sin(j)+1))*255);


matrix[i][j] = (int)(((.25*(Math.sin(i)+1))+(.25*(Math.cos(j)+1)))*255);

The Mandelbrot Set, which I previously blogged about here, is a more interesting surface to look at. To plot the Mandelbrot Set, you just need to replace the getMatrix method in createContents with getMandelbrotSet. The getMandelbrotSet method is as follows:

private static int[][] getMandelbrotSet(int xSize, int ySize) {

int[][] mandelbrotSet = new int[xSize][ySize];
int n = 0;
int nmax = 255;
double x,y,xnew,ynew,z2,cx,cy;

for(int i = 0; i<xSize; i++){
for(int j = 0; j<ySize; j++){
cx=-2.0+(3.*i)/xSize;
cy=1.5-(3.*j)/ySize;
n = 0;
x = 0;
y = 0;
z2 = 0;
while(n < nmax && z2 < 4){
xnew = x*x-y*y+cx;
ynew = 2*x*y+cy;
z2 = xnew*xnew+ynew*ynew;
x = xnew;
y = ynew;
n++;
}

if (n == nmax){
mandelbrotSet[i][j] = 0;
}
else{
mandelbrotSet[i][j] = n;
}
}
}
return mandelbrotSet;
}


The resulting 2-D surface looks like this:


BTW, many thanks to Greg Houston for providing the JavaScript web application I used to convert my source code into HTML format for inserting into my blog.

Sunday, September 21, 2008

How To Remotely Boot Up and Shut Down a Computer

On my local network at home, I have a MacBook and several "headless" Linux boxes, which I use to crunch numbers. Other people might have a headless computer on their network used as a file or web server. Some computers on your local network may be in another room or even in a different country if you have a VPN setup. I found that I needed a way to remotely boot up and shut down any host on my local network without leaving my chair. How could I possibly do this all from the command line on my mac?

The setup and implementation is extremely easy - if you know what to do! It took me several hours to get it all working, but I'll summarize the steps here for you and it should only take about 30 minutes maximum to setup. The instructions below are specific to booting up and shutting down a remote host running Ubuntu Hardy Heron from a Mac running OSX Leopard, but other combimations of OSs will also probably work with possible slight variations to the instructions.




1. Enter the BIOS of the remote host you want to remotely boot up/shut down and enable the Wake On LAN feature (WoL). Save changes and exit BIOS.

2. Boot up the remote host and determine its IP and MAC address by typing ifconfig at the command line. The IP address will look something like this: 192.168.25.9. For the MAC address, you'll need to look for the 6 hexidecimal numbers separated by colons in the text returned by the ifconfig command. It will look something like this: 00:78:A5:9C:E8:AB. Write it down.

-->ifconfig

3. Shut down the remote host.

4. Download Wake-On-LAN (wakeonlan-0.41.tar.gz) here to your mac. It's a Perl script written by José Pedro Oliveira that sends a magic packet to LAN cards connected to your local network. More information on how WoL works can be found here.

5. Open up "Terminal" on your Mac, and un-tar the tar.

-->tar -xvvzf wakeonlan-0.41.tar.gz

6. Move the wakeonlan executable file to /usr/bin to have access to the script via the command line.

-->cp wakeonlan /usr/bin

7. To remotely boot up the remote host, type at the command line: wakeonlan -i [local network domain] [MAC address] & , where the local network domain is a 4 number address separated by periods - the first three numbers match the first three numbers of the host's IP address and the last number is 255. The MAC address corresponds to the MAC address of the host you're trying to boot up.

-->wakeonlan -i 192.168.25.255 00:78:A5:9C:E8:AB &

8. To remotely shut down the host, ssh into the host and type:

-->sudo shutdown -P now

Piece of cake!

Thursday, September 18, 2008

Riding a Thin Line Bordered by Death

Last weekend in Whistler, B.C., my cousin, Brett, introduced me to downhill mountain biking a.k.a. "riding a thin line bordered by death". It's awesome. Here are some pics. Many thanks to Brett's friend Craig for the awesome action shots.

Brett catching air off a boulder right before the impact of the landing caused the rear derailleur to get sucked into the wheel, break off, and destroy Brett and the bike.




The "containers".

This feature looks waaaay worse when you're standing on top of it looking down. If you're out of control after the landing, you'll fall down a ravine.

Wooden platforms are suspended from a foot to 30 feet off the ground and can be VERY narrow. This it literally a thin line bordered by death.

If clearing a 10 foot table top is too tame by itself, you can twist your handlebars 180 degrees while in the air and then back right before you land.

For a "step up" you have to be going mach 5 to clear the gap and make it to the landing.

If the falls off the wooden platforms and cliffs or the crash landings don't kill you, there's always the trees you could hit going 30 mph or the giant potholes, roots, and rocks that can buck you off your bike and either toss you down a cliff or into a tree. For my first time, I'm just proud of myself for surviving unscathed and being able to see Brett and Craig in action.

Diedre 5.7, Squamish - Climbing Beta

Climbing the 6-pitch Diedre outside of Squamish, British Columbia is a blast. Late Thursday night, my cousin and I cruised up from Seattle to Whistler for a three-day weekend in British Columbia. He wanted to introduce me to downhill mountain biking at Whistler, and I thought I'd introduce him to outdoor rock climbing in the world-class climbing venue of Squamish. I decided to try out Diedre or Banana Peel, both 5.7, on the Apron, whichever route had less traffic when we got to the base. From reading other people's trip reports, I figured most people would try to get there at the crack of dawn, so I thought getting there late morning would be the best bet to not have to wait in a queue at the bottom of the route. When we got to the base of the routes, no one was on Banana Peel, and the first two pitches of Diedre were free. Two British guys arrived five minutes behind us, and they said they already did Diedre and were going for Banana Peel. At that point we decided to do the 6-pitch 5.7 Deirdre. Getting there late moring seems to be the best time. Here's a nice photo of Diedre and Banana Peel.



Rack:
1 set of cams from small fingers up to #3 Camalot
1 set of nuts from medium to large
half dozen quick draws
half dozen slings

Beta:
The trickiest part of the entire climb was finding the climb. From the parking lot below the Apron, take the trail about 30 feet until you see a dirt trail going into the forest on your left with a huge log with steps cut into it. Take that trail up to the base of the Apron and traverse left along the base for approximately 50 yards. You'll find a right traversing cut in the rock going up and right at about 40 degrees. Scramble up that cut about 100 yards to the base of Diedre and Banana Peel. You can see a birch tree about 40 feet straight up from the base of the climb.

Me on top of the crux third pitch.

Pitch 1 and 2 are slabby runouts. I was able to place a few pieces on pitch 1 and sling the birch tree. Pitch 2 was a short slab traverse to the left with no place for gear. Pitches 3 through 5 were very long and followed a right-facing corner. Pitches 3 and 4 are very similar in difficulty and take plenty of gear. The angle lessens on pitches 5 and 6 and the crack pinches down in spots making 20 to 30 foot runouts necessary. Pitch 6 is short and at such a low angle, you almost don't need to use you're hands on the handholds. We walked off the ledge to the right without roping up at all, which led to a long descent through the forest and back down to the car.

My cousin, Brett, enjoying the view from the top.

Thursday, September 11, 2008

Mandelbrot Set

The Mandelbrot Set is a great introduction to understanding fractals. A fractal is defined as an object with repeating patterns at different scales. Nature makes the best fractals, and they are everywhere you look once you develop an eye for them - clouds, trees, rivers, moutains, leaves, circulatory and nervous systems, etc. The Mandelbrot Set is a computer generated image that also displays self similarity at different scales along with striking beauty. Programming the algorithm to create an image of the Mandelbrot Set is a fun way to test out a new programming language. This complicated mathematical object is actually created by a rather simple procedure. For some complex number c, we start with z = 0 and evaluate subsequent z's by the iteration



z = z^2 + c.

If z remains finite, even after an infinite number of iterations, then the point c is a member of the Mandelbrot set. Since infinity is a very big number, it wouldn't be practical to iterate the equation infinity times so a smaller number like 255 iterations is enough for the job. The points c that are a member of the set get colored black. The points not a member of the set can be colored and given a brightness proportional to the number of iterations taken to escape.

To program the algorithm, you need to think of a square plane of pixels on your computer screen to be the complex plane, where each pixel on that square represents the coordinates of a unique discrete complex number given by the the x and y location of the real and imaginary axis respectively. For each pixel, you need to determine its location on the complex plane and then using that value, seed the above equation with it as c. Then you enter a loop and continuously reiterate that equation until you reach some preset maximum number of iterations like 255. If at any time during the loop, the magnitude of z is greater than 2, you can break out of the loop because you know that seed value doesn't belong to the Mandelbrot Set, and you can assign a color value to that pixel based on how many iterations it took to exit the loop. Otherwise, the seed value is part of the Mandelbrot Set and you can color it black. You do that for every pixel in your square, and the Mandelbrot set appears!

Following are some screen shots of the Mandelbrot Set from a program I recently wrote in Java using the SWT libraries. I added capabilites so I could click on a part of the Mandelbrot Set, triggering the program to zoom deeper to reveal more details. By the way Mandelbrot means "almond bread" in German.












Wednesday, September 10, 2008

Knowledge

Information is valuable. It's even more valuable when shared.

All too often the wrong decisions are made because of a lack information or the information at hand is inaccurate. I find myself searching for information quite often whether it's because I want to buy the right product, satisfy my curiosity, or to decide what path to go down at one of life's crossroads. I know that in 99.999% of cases, someone has already asked the questions I'm trying to answer. If only I could have access to their solution! A long time ago before paper and written language was invented, knowledge was passed on generation to generation through spoken language. What a concept! Imagine if every generation had to start at square one, conceptualize and invent their own tools from scratch and make all the same mistakes of their ancestors!

Next came one of the greatest human inventions ever - written language. The sum of all human knowledge from everyday stuff to more obscure information could be bound an stored on a library shelf and accessed by anybody who could read. A single person could amass an entire lifetime of information from reading other people's works and doing her own research and sum it all up in a single volume to be read by millions of people in the present and forever into the future. A giant leap in the rate of technological advancements corresponded to the this single event even though people probably hardly noticed.

We've now taken the next quantum leap of information sharing with the internet. In less than a minute, you can do a search from your living room to find out what the hottest pepper in the world is or have access to a public database of DNA sequence maps of complete chromosomes or genomes of over 4600 species (including human) and counting. What we choose to to with all this information at our fingertips now will be forever recorded in history books. We can do good with it, do evil with it, or just remain ignorant and let things happen around us.

When I look around at what some people or governments are doing, I jump to the conclusion that they HAVE to be misinformed. Otherwise why on earth would they be doing what they're doing? Or perhaps they have some information that I don't! Thus far in my short life I've read a lot, traveled a lot and asked many questions. With this blog, I hope to disseminate valuable information filtered through an objective non-biased view and make it available to others to use in hopefully good ways. There's been many times where I've been searching for how to do something for hours, and I came across someone's blog to find the exact solution I was looking for. I hope that I can return the favor to other people with this blog and also learn more myself from them!

Here's a link to a Will Smith speech that just popped in my head regarding reading.