Monday, November 28, 2011

Compiling MPI.NET under Ubuntu Oneiric

I recently wanted to experiment with parallel programming and - since my language of choice is C# - thought it might be interesting to try out using Message Passing.  There are two main libraries available: The Message Passing API (MPAPI) and MPI.NET.  MPAPI provides an independent framework (that does not rely on the Message Passing Interface (MPI) or MPI-2 standards), while MPI.NET provides low-level bindings to the MPI-2 standard directly.

I have done some previous work with MPAPI and found it to be a capable framework that I would highly recommend.  However, that initial choice was because I had significant difficulty compiling MPI.NET under Ubuntu.  I've since resolve those difficulties, so today we will discuss building MPI.NET under Ubuntu (Oneiric).

Step 1: Download MPI.NET version 1.0.0 from the MPI.NET download page.  You want the mpi.net-1.0.0.tar.gz package (source code for Unix).

Step 2: Untar the files and enter the directory:
tar xzvf mpi.net-1.0.0.tar.gz
cd mpi.net-1.0.0
Step 3: Install build prerequisites
sudo apt-get install mono-complete libtool automake autoconf build-essential
Step 4: Install an MPI framework

This is subject to some choice.  Two good libraries are OpenMPI and MPICH2 which you can install through apt get via one of (do not execute both) of the following commands:
sudo apt-get install libopenmpi-dev openmpi-bin openmpi-doc
or
sudo apt-get install mpich2 libmpich2-dev
 Step 5: Create a symbolic link from /usr/bin/ilasm to /usr/bin/ilasm2.  For some reason that is not clear to me MPI.NET looks for ilasm2 which is not present (wrapped into ilasm?) in later versions of Mono.
ln -s /usr/bin/ilasm /usr/bin/ilasm2
Step 6: Download and install patches

Several source files need to be patched to allow successful compilation (see this helpful mailing list posting).  Download Makefile.am.patch, Unsafe.pl.patch, and configure.ac.patch from this repository.  Save them in the mpi.net-1.0.0 directory.

Apply the patches with the following three commands:
patch configure.ac < configure.ac.patch
patch MPI/Unsafe.pl < Unsafe.pl.patch
patch MPI/Makefile.am < Makefile.am.patch
These should all complete successfully.  If not, check the exact filename you used when you saved the patch.  Rename them (or modify the above three commands), as appropriate.

Step 7: Run the standard compilation sequence.  Everything should complete successfully:
sh autogen.sh
./configure
make
make install
The desired MPI.dll and MPI.dll.config is in the MPI subdirectory of the mpi.net-1.0.0.

Step 8: Try creating a hello world program to verify MPI.NET works.

In a new folder, create a source file (Hello.cs) containing a Hello World program similar to the one shown in the MPI.NET tutorial, such as:

using System;
using MPI;

class MPIHello
{
    static void Main(string[] args)
    {
        using (new MPI.Environment(ref args))
        {
           Console.Write("Greetings from node {0} of {1}\n",
                         Communicator.world.Rank,
                         Communicator.world.Size);
        }
    }
}

Copy MPI.dll and MPI.dll.config to this folder and compile under mono:
gmcs Hello.cs -reference:MPI.dll - target:exe -out:Hello.exe
Compilation should succeed without errors or warnings.

Run the resultant program using mpiexec to launch four threads:
mpiexec -np 4 ./Hello.exe
 If the resultant output is (the order of lines may vary), then everything is working as expected:
Greetings from node 0 of 4
Greetings from node 2 of 4
Greetings from node 1 of 4
Greetings from node 4 of 4
If all this worked, you should now have a working installation of MPI.NET and can use the MPI-2 framework to write parallel and distributed programs.

Further reading

7 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. I've compiled MPI.NET in a laptop with Ubuntu 10.04 LTS, all worked well. Then I tried to do the same in a cluster with Suse and powerpc64 processors, the configure script gave me no error. Nevertheless doing make I obtained the following error message:

    >
    Making all in MPIUtils
    make[1]: Entering directory `/gpfs/home/ULP010/jmedina/mpi.net-1.0.0/MPIUtils'
    make[1]: Nothing to be done for `all'.
    make[1]: Leaving directory `/gpfs/home/ULP010/jmedina/mpi.net-1.0.0/MPIUtils'
    Making all in MPI
    make[1]: Entering directory `/gpfs/home/ULP010/jmedina/mpi.net-1.0.0/MPI'
    if /bin/sh ../libtool --tag=CC --tag=CC --mode=compile mpicc -DPACKAGE_NAME=\"MPI.NET\" -DPACKAGE_TARNAME=\"mpi-net\" -DPACKAGE_VERSION=\"0.6.0\" -DPACKAGE_STRING=\"MPI.NET\ 0.6.0\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE=\"mpi-net\" -DVERSION=\"0.6.0\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -DHAVE_MPI=1 -I. -I. -g -O2 -MT cbridge.lo -MD -MP -MF ".deps/cbridge.Tpo" -c -o cbridge.lo cbridge.c; \
    then mv -f ".deps/cbridge.Tpo" ".deps/cbridge.Plo"; else rm -f ".deps/cbridge.Tpo"; exit 1; fi
    mpicc -DPACKAGE_NAME=\"MPI.NET\" -DPACKAGE_TARNAME=\"mpi-net\" -DPACKAGE_VERSION=\"0.6.0\" "-DPACKAGE_STRING=\"MPI.NET 0.6.0\"" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE=\"mpi-net\" -DVERSION=\"0.6.0\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -DHAVE_MPI=1 -I. -I. -g -O2 -MT cbridge.lo -MD -MP -MF .deps/cbridge.Tpo -c cbridge.c -fPIC -DPIC -o .libs/cbridge.o
    xlc_r: 1501-218 (W) file 0.6.0" contains an incorrect file suffix
    xlc_r: 1501-228 (W) input file 0.6.0" not found
    xlc_r: 1501-208 (S) command option D is missing a subargument
    make[1]: *** [cbridge.lo] Error 1
    make[1]: Leaving directory `/gpfs/home/ULP010/jmedina/mpi.net-1.0.0/MPI'
    make: *** [all-recursive] Error 1

    with gcc as mpicc choice the result was the same.
    has someone a hint about the reason of this error?

    thanks

    Juan S.

    ReplyDelete
  3. I'm not entirely sure. Does "sh autogen.sh" completely successfully in step 7?

    ReplyDelete
  4. Sorry by the delay, I was busy in another task.

    Apparently, "sh autogen.sh" works without any warning, indeed the output is:

    sh autogen.sh
    --> Running aclocal
    --> autoheader not needed
    --> Running autoconf
    --> Running libtoolize
    --> Running automake

    and nothing else, as far as I remember is the same answer I got from my laptop using Ubuntu.

    thanks

    Juan S.

    ReplyDelete
  5. Really appreciate you post on this, wish I saw this littler earlier before compiling everything by hand :/

    Anyway, I ran into one issue. When I do mpiexec (say with two processes)with the simplest HelloWorld kind of program shown above, I see two outputs but they are independent copies and they both see world size as 1 instead of 2. Any thoughts on this?

    Thanks

    ReplyDelete
  6. Update on my comment. I got it resolved by going with OpenMPI.

    ReplyDelete
  7. I am using CentOS 7 with openMPI.
    I have some error to install mpi.net.

    I apply the patches with the following three commands:

    patch MPI/Unsafe.pl < Unsafe.pl.patch

    Downloaded this patch from --->
    https://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/sys-cluster/mpi-dotnet/files/?hideattic=0

    After configuring mpi.net, I do write make command.

    In this section we have error :

    CustomUnsafe.cs
    CustomUnsafe.cs(112,41): error CS1525: Unexpected symbol `;'
    CustomUnsafe.cs(3238,12): error CS1525: Unexpected symbol `switch'
    CustomUnsafe.cs(3240,16): error CS1525: Unexpected symbol `case'
    CustomUnsafe.cs(3287,1): error CS8025: Parsing error
    Compilation failed: 4 error(s), 0 warnings

    Please help me, how to fix it.

    ReplyDelete