Using the Darwin cluster

Darwin Cluster Wiki

Setting up passwordless SSH
Darwin specifications
Logging in
Compiling MPI and OpenMP programs
Running MPI programs
Timing your runs
MPI example
OpenMP example
Julia example
Emacs setup
Star-P setup


Setting up passwordless SSH

Being able to move among nodes without entering a password will make your life much more enjoyable.
  1. Run ssh-keygen on a Unix machine you typically use (can be Athena, or a Darwin cluster head node). Accept the default settings and leave the passphrase blank. This creates files in ~/.ssh
  2. Append the contents of ~/.ssh/id_rsa.pub to the file ~/.ssh/authorized_keys on each machine you want to be able to connect to. The Darwin cluster nodes share a filesystem, so you only need to do this once on one of the head nodes.
  3. Copy the file ~/.ssh/id_rsa (private key) to the same location on each machine you want to connect from. Again, once this file is in ~/.ssh on Darwin you are all set for the cluster.
  4. The file id_rsa needs to have strict permissions. If you get errors about this, run chmod 400 id_rsa.
You can copy files to remote machines using scp:
scp file user@machine:path


Darwin specifications

  • Darwin compute cluster
    • Head node: beagle.darwinproject.mit.edu
    • Nodes: 128
    • Per-node CPU: 2 x 2-core 3.00GHz Intel(R) Xeon(TM), 4MB L2 cache
    • Per-node memory: 8 GB
  • Darwin visualization cluster
    • Head node: evolution.darwinproject.mit.edu
    • Nodes: 60
    • Per-node CPU: 2 x 2-core 2.66GHz Intel(R) Xeon(TM), 4MB L2 cache
    • Per-node memory: 6 GB
On Linux, hardware info is available via less /proc/cpuinfo and less /proc/meminfo.
The top command is useful to see how much CPU and memory everybody's jobs are using. In top, hit "M" to sort by memory use. Hit "u" and type your username to see just your processes.


Logging In

ssh to beagle.darwinproject.mit.edu or evolution.darwinproject.mit.edu with your athena username and password.

If you are on a windows machine, you can download SecureCRT or Putty from MIT, MIT certificate required). Or you can use any other SSH client.


Compiling MPI and OpenMP programs

For MPI programs, use mpicc for C programs, mpiCC for C++ programs, mpif77 for fortran programs, as follows:
mpicc mytest.c -o test
or,
mpiCC mytest.cc -o test
or,
mpif77 mytest.f -o test

For OpenMP programs you need to use the Intel Fortran/C Compilers. Do the following on beagle:
source /opt/intel/cc/9.1.051/bin/iccvars.sh
then,
icc -O -openmp -o test mytest.cc
or,
ifc -O -openmp -o test mytest.f


Running MPI programs

After compiling MPI programs, use mpirun to execute:

mpirun -np # -machinefile hostfile ./yourMPIProgram

where # is the number of processors and yourMPIProgram is the MPI executable to be run .
"hostfile" is a text file listing all the hosts you want to use. It might look like this:

compute-1-1
compute-1-2
compute-1-3
compute-1-4

Look at /etc/hosts to see the names of the compute nodes.


Timing your runs

You can use the command time to time your runs. For example,

time ./myprog

returns something like

real 0m0.958s
user 0m0.180s
sys 0m0.170s

real is the wall clock time elapsed.

Timing MPI programs is similar,

time mpirun -np 4 ./hello++

This method is not very accurate. For accurate timing, use the function MPI_WTime


MPI example

#include "mpi.h"
#include "unistd.h"
#include "stdio.h"

int main(int argc, char **argv)
{
  char hostname[256];
  int size,rank;

  MPI_Init(&argc, &argv);

  MPI_Comm_size(MPI_COMM_WORLD, &size);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);

  gethostname(hostname, sizeof(hostname));

  printf("Hi, I am %d of %d and my hostname is %s\n", rank, size, hostname);

  MPI_Finalize();
}


OpenMP example


#include <math.h>
#include <stdio.h>

#define N 16384
#define M 10

double dotproduct(int, double *);


double dotproduct(int i, double *x)
{  
  double temp=0.0, denom;
  int j;

  for (j=0; j<N; j++) {
    // zero based!!
    denom = (i+j)*(i+j+1)/2 + i+1;
    temp = temp + x[j]*(1/denom);  
  }

  return temp;
}


int main()
{
  double *x = new double[N];
  double *y = new double[N];
  double eig = sqrt(N);
  double denom,temp;
  int i,j,k;

  for (i=0; i<N; i++) {
    x[i] = 1/eig;
  }

  for (k=0;k<M;k++) {

    y[i]=0;

    // compute y = Ax
#pragma omp parallel for shared(y)
    for (i=0; i<N; i++) {     
      y[i] = dotproduct(i,x);
    }
    
    // find largest eigenvalue of y
    eig = 0;    
    for (i=0; i<N; i++) {
      eig = eig + y[i]*y[i];
    }    
    eig = sqrt(eig);
   
    printf("The largest eigenvalue after %2d iteration is %16.15e\n",k+1, eig);

    // normalize
    for (i=0; i<N; i++) {
      x[i] = y[i]/eig;
    }
  }
}


Julia example

A regularly-updated copy of Julia is available on Darwin under /home/bezanson/julia. One of Julia's charming features is that it can be run by anyone, from anywhere, without any install or setup. Type /home/bezanson/julia/julia to run it. There is also a world-writable directory /home/bezanson/julia/data in case that is useful.

You can add processors to Julia's pool from the prompt using a cell array of machine names:

julia> @time @parallel (+) for i=1:10000000; randn(); end
elapsed time: 1.0429379940032959 seconds
-842.00907574328687133

julia> @time @parallel (+) for i=1:10000000; randn(); end
elapsed time: 0.58234810829162598 seconds
430.07946679243082144

julia> addprocs_ssh({"compute-1-1","compute-1-2"})
various junk is printed

julia> @time @parallel (+) for i=1:10000000; randn(); end
elapsed time: 3.28881287574768066 seconds
2124.42978527200511962

julia> @time @parallel (+) for i=1:10000000; randn(); end
elapsed time: 0.31914687156677246 seconds
283.82680807441192883
Here we summed 10000000 normal-random numbers using a parallel for loop. Julia can start additional processes via SSH, provided you have passwordless access to the nodes in question. You can start more than one process on a given node by listing the name of the node multiple times.

Note one particular minor annoyance: due to Julia's Just-In-Time (JIT) compilation model, things take longer the first time you do them. The extra delay is typically about 1-3 seconds. As the code cache warms up over a session, these delays become shorter and rarer.

(Optional!) If you would like to check out and build your own copy of Julia, you can add your SSH public key to the github account we're using, under github's "Account Settings". If you have your own github account and would like access to our repository through it, let us know. If you'd like to get a little deeper into Julia and possibly even contribute changes, fixes, example code, etc. you should make your own github account (if you don't have one already) and ask us for push/pull access.


Emacs setup

An emacs mode for Julia is available. Copy /home/bezanson/.emacs to your home directory, or add the following to your .emacs file:
(require 'julia-mode "/home/bezanson/julia/contrib/julia-mode.el")


Star-P setup

First copy some configuration information by running:
cp -r /home/bezanson/.starp ~
To run Star-P, you must be logged in to evolution. Run:
/share/apps/starp/2.7.0/bin/starp -l /home/bezanson/license.lic

If you see an error like from mpd on tile-0-1, invalid port info, it might be due to a mismatched public/private key pair in ~/.ssh. Try re-running ssh-keygen, hit enter (blank) for the passphrase, and paste ~/.ssh/id_rsa.pub into ~/.ssh/authorized_keys.