{"id":837,"date":"2013-09-30T22:03:55","date_gmt":"2013-09-30T11:03:55","guid":{"rendered":"http:\/\/www.zamaudio.com\/?p=837"},"modified":"2013-10-01T00:05:19","modified_gmt":"2013-09-30T13:05:19","slug":"create-test-mpi-cluster-using-virtualbox-images","status":"publish","type":"post","link":"https:\/\/www.zamaudio.com\/?p=837","title":{"rendered":"Create test MPI cluster using VirtualBox images"},"content":{"rendered":"<p>This is a mini howto for creating a small MPI test cluster using virtual machines under linux.<\/p>\n<p>We will be using Debian netinst CD for this howto as it is convenient to install a minimal system with no X subsystem, but any *nix environment would suffice.<\/p>\n<p>This howto assumes you are running some form of linux as your host operating system.<\/p>\n<p><strong>Steps:<\/strong><\/p>\n<p>Check how many bits your kernel and userland is, ie. 32 bit or 64 bit.<\/p>\n<p>Grab the Debian netinst CD of the same bitness (this could save you a lot of trouble later with shared libraries in the wrong place across cluster virtual machines).<\/p>\n<p>Install VirtualBox on the host operating system.<br \/>\nOn the host, also install the following:<br \/>\n<code>$ sudo apt-get install uml-utilities bridge-utils<\/code><\/p>\n<p>Create a single instance of Debian with the following parameters:<br \/>\n1 cpu, 768MB ram, 6GB dynamically allocated hard disk image, bridged mode network interface.  Select expert install and do not choose Desktop environment (no X), but do select SSH Server.  Use the same username as your main host pc for easy ssh setup.<\/p>\n<p>Fire up your new instance, log in as root and run<\/p>\n<p><code># apt-get install mpich2<\/code><\/p>\n<p>Log out and log in as your regular user and run<\/p>\n<p><code>$ ssh-keygen -t rsa -b 2048<\/code><\/p>\n<p>Use empty passphrase, and copy the contents of id_rsa.pub onto your host machine in ~\/.ssh\/authorized_keys.<\/p>\n<p>If you already have an ssh key on your main machine, you can also authorise your key on the virtual machine by doing the reverse, otherwise create a new key on the host too and repeat.<\/p>\n<p>Now you should be able to secure shell into your virtual machine without a password (using public key authentication) and check the date on the remote machine using:<\/p>\n<p><code>(host)$ ssh IPAddressOfVirtual date<\/code><\/p>\n<p>and likewise on the virtual machine terminal:<\/p>\n<p><code>(virt)$ ssh IPAddressOfHost date<\/code><\/p>\n<p>Clone your VM a few times (as many nodes as you need).<br \/>\nFix up the ssh auth and ip addresses etc:<\/p>\n<p>A vital trick is to remove the persistent network interface udev rules on the cloned virtual image otherwise the network card will not come up automatically:<br \/>\n<code>(cloned)# rm \/etc\/udev\/rules.d\/70-persistent-net.rules<\/code><\/p>\n<p>Also, you need to put your network card into promiscuous mode and create a bridge network interface on the host os and create as many virtual network interfaces (tun) as you have nodes:<br \/>\nUse this script to initialise your network before you fire up VirtualBox (replace damien with your username):<br \/>\n<code><br \/>\n#!\/bin\/bash<br \/>\n# Don't need these, so they die<br \/>\nifconfig vbox0 down<br \/>\nifconfig eth1 down<br \/>\n# Pull down the main card<br \/>\nifconfig eth0 down<br \/>\n# Throw up a bridge<br \/>\nbrctl addbr br0<br \/>\n# Add my main card to the bridge<br \/>\nbrctl addif br0 eth0<br \/>\nifconfig eth0 0.0.0.0 promisc<br \/>\n# Bridge goes up<br \/>\nifconfig br0 up<br \/>\n# Bridge obtains an IP address<br \/>\ndhclient br0<\/p>\n<p># Give me a virtual adapter<br \/>\nmodprobe tun<br \/>\ntunctl -t tap0 -u damien<br \/>\n# Add the adapter to the bridge<br \/>\nbrctl addif br0 tap0<br \/>\nchmod 0666 \/dev\/net\/tun<br \/>\nifconfig tap0 up<\/p>\n<p># Give me a virtual adapter<br \/>\nmodprobe tun<br \/>\ntunctl -t tap1 -u damien<br \/>\n# Add the adapter to the bridge<br \/>\nbrctl addif br0 tap1<br \/>\nchmod 0666 \/dev\/net\/tun<br \/>\nifconfig tap1 up<\/p>\n<p># Give me a virtual adapter<br \/>\nmodprobe tun<br \/>\ntunctl -t tap2 -u damien<br \/>\n# Add the adapter to the bridge<br \/>\nbrctl addif br0 tap2<br \/>\nchmod 0666 \/dev\/net\/tun<br \/>\nifconfig tap2 up<\/code><\/p>\n<p>This creates 3 virtual interfaces for your bridge and attaches them.  In VirtualBox you need to set each instance to a bridged interface using a unique tap0-tap2 virtual interface so each instance gets its own IP address. (Of course you can put more if you need).<\/p>\n<p>Now, the thing with MPI is that the executable must be accessible on all clusters in the same directory!<br \/>\nA good solution would be to mount a NFS share at the same mountpoint on all nodes, but I hacked up a simple script that copies the executable to the same directory on all nodes separately after rebuilding it.<\/p>\n<p>Create &#8216;hosts&#8217; file:<br \/>\n<code>ipaddress1<br \/>\nipaddress2<br \/>\n...<\/code><\/p>\n<p>Makefile (fix indentation):<br \/>\n<code>SHELL=\/bin\/bash<br \/>\nPWD=$(shell pwd)<br \/>\nN=$(shell cat hosts|wc -l)<br \/>\nPROG=hello<br \/>\n#<br \/>\nbuild:<br \/>\n        mpicc $(PROG).c -o $(PROG)<br \/>\n#<br \/>\nrun: build<br \/>\n        $(shell for h in $(shell cat hosts); do ssh <strong>$<\/strong>$h 'mkdir -p $(PWD)'; scp $(PROG) <strong>$<\/strong>$h:$(PWD); done) mpiexec.hydra -f hosts -n $N .\/$(PROG)<br \/>\n#<br \/>\nclean:<br \/>\n        $(shell for h in $(shell cat hosts); do ssh <strong>$<\/strong>$h 'rm -f $(PWD)\/$(PROG)'; done)<\/code><\/p>\n<p>Now try running a simple MPI program such as the following:<br \/>\nhello.c:<br \/>\n<code><br \/>\n#include &lt;stdio.h&gt;<br \/>\n#include &lt;mpi.h&gt;<br \/>\n#<br \/>\nint main (argc, argv)<br \/>\n     int argc;<br \/>\n     char *argv[];<br \/>\n{<br \/>\n  int rank, size;<br \/>\n  MPI_Init (&argc, &argv);\t\/* starts MPI *\/<br \/>\n  MPI_Comm_rank (MPI_COMM_WORLD, &rank);\t\/* get current process id *\/<br \/>\n  MPI_Comm_size (MPI_COMM_WORLD, &size);\t\/* get number of processes *\/<br \/>\n  printf( \"Hello world from process %d of %d\\n\", rank, size );<br \/>\n  MPI_Finalize();<br \/>\n  return 0;<br \/>\n}<\/code><\/p>\n<p>Execute &#8216;make run&#8217; and you should see this output:<br \/>\n<code>(host)$ make run<br \/>\nmpicc hello.c -o hello<br \/>\nmpiexec.hydra -f hosts -n 2 .\/hello<br \/>\nHello world from process 0 of 2<br \/>\nHello world from process 1 of 2<br \/>\n$<\/code><\/p>\n<p>Enjoy!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a mini howto for creating a small MPI test cluster using virtual machines under linux. We will be using Debian netinst CD for this howto as it is convenient to install a minimal system with no X subsystem, but any *nix environment would suffice. This howto assumes you are running some form of [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[7,5],"tags":[],"_links":{"self":[{"href":"https:\/\/www.zamaudio.com\/index.php?rest_route=\/wp\/v2\/posts\/837"}],"collection":[{"href":"https:\/\/www.zamaudio.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.zamaudio.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.zamaudio.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.zamaudio.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=837"}],"version-history":[{"count":13,"href":"https:\/\/www.zamaudio.com\/index.php?rest_route=\/wp\/v2\/posts\/837\/revisions"}],"predecessor-version":[{"id":850,"href":"https:\/\/www.zamaudio.com\/index.php?rest_route=\/wp\/v2\/posts\/837\/revisions\/850"}],"wp:attachment":[{"href":"https:\/\/www.zamaudio.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=837"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.zamaudio.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=837"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.zamaudio.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=837"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}