Compiling MPI Programs in Visual Studio
Last updated: [4/26/15]
1.1. Have Visual Studio 2005/2008 (everything in this tutorial probably also works for 2010/2012 with slight differences/modifications) installed and probably a good idea to make sure it’s patched to the latest service pack.
1.2. Download and install either one of the two available packages:
Microsoft HPC Pack 2008 SDK with SP2 (recommended)
Microsoft HPC Pack 2008 R2 SDK with SP4
I'm not sure what the R2 version is, but it didn't work for me, and you cannot install both.More details here, and later in this tutorial section 5.1.
1.3. Open Visual Studio 2005/2008.
2.1. Create a "New Project" by going to: File → New → Project.
2.2. Select "Visual C++" and then "Win32" from the menu on the left. Select "Win32 Console Application" on the right. Enter a location to save the project and name the project. Then press OK. These steps are illustrated in the picture below.
2.3. In the wizard, click the "Next >" button.
2.4. Uncheck the "Precompiled header" checkbox and press the "Finish" button. This will remove the dependency from any “stdafx” files. The proper selections are shown in the following picture:
2.5. The project will now be created. In the .cpp file, change the given "_tmain" to just "main" and change "_TCHAR* argv[]" to just "char* argv[]" so it is compatible with the MPI_Init call, as shown below:
#include <iostream>
#include <mpi.h>
using namespace std;
//int _tmain(int argc, _TCHAR* argv[])
int main(int argc, char* argv[])
{
cout << "Hello World\n";
return 0;
}
1.9. You can delete unnecessary files in the "Solution Explorer". You can delete "stdafx.h" and "stdafx.cpp", but be sure to remove all respective #include from the .cpp file if you do this. To delete a file, right click on it and select "Remove".
3.1. Now Right click on the project in "Solution Explorer", named “mpiProject” in the above image, and select "Properties". Highlight and expand "Configuration Properties" on the left.
Before making any changes to the profile, select "All Configurations" from the "Configuration:" drop-down box at the upper left if you want the changes to be applied to ALL the different configurations (release, debug, etc.)
Select "C/C++" from the tree at the left, then select "General" under that. In "Additional Include Directories" on the right, put the directory in which you installed the SDK's include files (in Step 1.2). In the default case, this is: "C:\Program Files\Microsoft HPC Pack 2008\Include". Include the quotes in the field.
[Optional] Select "Advanced" under the same "C/C++" menu on the left. In "Compile As" on the right side, select "Compile as C Code (/TC)" if your program is just C and not C++.
Select "General" under the "Linker" menu on the left. In "Additional Library Directories" on the right, put the directory in which you installed the SDK's lib files (in Step 1.2). In the default case, this is: "C:\Program Files\ Microsoft HPC Pack 2008\Lib\i386", (including the quotes in the field) for the 32-bit version. Choose the amd64 folder for the applicable 64-bit version. NOTE that shown below the Win32 profile is active, so the matching i386 should be too. If you fail to choose the proper 32/64 bit library, you will get unresolved external symbol errors when using MPI functions.
Select "Input" under the "Linker" item in the tree on the left. In "Additional Dependencies" on the right side, type in "msmpi.lib", without the quotes, in order to use the MPI libraries.
3.2. Compile your program by selecting "Build Solution" from the "Build" menu at the top of the screen. Should work without errors and you can begin using the MPI functions!
4.1: Getting your program to run with multiple threads:
If you compile and run the program now, you will find that the program only runs with 1 thread, even if you have a dual or quad-core computer. In order to run MPI, you’ll need to run the program through mpiexec.exe and specify the number of cores to use.
For now, go ahead and click the Start menu, and select Run. Type cmd and hit enter. Go ahead and browse to your project directory. If you've never used the command line before, you can change directories with “cd <directory name>”, list the contents of the current directory with “dir”, and go back a directory with “cd ..”.
Once you browse to your project directory, type mpiexec MPI_Tutorial_1.exe. In the picture above, you’ll see that it ran with two threads. That’s because I’m currently running on a computer with two processor cores. In the next command, you see that by specifying with a
“-n” switch, you can force your program to start with any number of threads (See the final image below).
If you encounter an error when trying to run your program with mpiexec with Windows XP, search how to fix the issue by applying a hotfix.
4.2: Getting your program to run through the GUI (without having to type on the command line)
Wouldn't it be nice if we didn't have to type on the command line every time we wanted to run our program? Well, we can configure Visual Studio to do this automatically. Right click on the Solution Explorer window, select your project, right click, and select properties.
A note for Visual Studio Professional users: If you have a professional version of Visual Studio (2005 or 2008), you are in luck. By selecting the Debugging Category, you can select the “Debugger to launch” drop down list. If you see MPI Cluster Debugging, or something similar, then you should definitely use that. This offers many advantages over the express and standard versions of Visual Studio. These advantages will be covered in Part 5 (you can actually skip to Part 5 right now). If you are using an express or standard version of Visual Studio, don’t panic. Please follow the text below in order to get your program to run with the build and run command in Visual Studio, but know that it has debugging limitations.
4.3 Running multiple threads in a single console window
If you DON’T have the professional version of Visual Studio, then this is your FINAL step. You must first specify options for running mpiexec:
Make the command target mpiexec.exe (including the full path). As command line options, you can specify the number of processors you want here directly with “-n” followed by the integer number, and just as importantly, specify your executable; "$(TargetPath)" will use the project settings to specify it automatically for you. You should include your target path with quotation marks in case it contains spaces. Go ahead and click Apply/OK, and run your project. Visual Studio should be able to compile and run your program just as it did before. Note that it runs ALL threads within a single command window, and cannot be debugged with the GUI (breakpoints, watch, etc.). But if you have the professional version of Visual Studio, keep reading...
4.5 Simple sample code
Now you can start using the MPI functions, like in this simple example:
#include <iostream>
#include <mpi.h>
using namespace std;
//int _tmain(int argc, _TCHAR* argv[])
int main(int argc, char* argv[])
{
int myid, num_threads;
int err = MPI_Init(&argc, &argv); //Start MPI
if (err != MPI_SUCCESS) { //Check success
MPI_Abort(MPI_COMM_WORLD, err);
return 3;
}
MPI_Comm_size(MPI_COMM_WORLD, &num_threads); //Get quantity of threads
MPI_Comm_rank(MPI_COMM_WORLD, &myid); //Get current exe’s thread ID
if (myid == 0) //Display text (only once from the master exe, myid==0)
cout << "MPI initialized with " << num_threads << " thread(s).\n";
cout << "This is thread " << myid << ".\n";
MPI_Finalize(); //Exit MPI
return 0;
}
Getting the FULL debugging support in MPI is a whole new task and (most likely) only works with the professional version of MS Visual Studio that includes the MPI Cluster Debugger as shown in the previous steps. The huge advantage is that you will be able to use the GUI’s real-time breakpoints, watch list, call stack, etc. with multiple threads!
5.1 Installing SP1 and hotfixes
First, make sure the following are installed in this order:
NOTE: Microsoft has a general guide here with all installation packages. I noticed that the R2 Client Utilities is required even for the regular HPC SDK pack if you want the GUI debugger Add-on to function.
When you do get it working, you will see the option Tools -> Cluster Debugger Configuration in the IDE:
You will NOT need any of the commands entered in the MPI Cluster Debugger configuration properties from Step 4.3. Instead you will enter all the new details into the NEW plug-in window. (The steps can be found here.)
Note that I had to include my own custom library file in the “Additional files to deploy” because this add-in creates a temporary folder where it copies all the necessary files just before execution (a useful feature for cluster computing, but not really for local computing).
One difference you may notice immediately upon successful execution is that EACH process now receives its OWN console window! This is beneficial when each CPU is writing text to the console. Notice that a main console window opens first; this parent window launches the actual MPI processes and reports any error codes if the threads end. Use system("pause"); at the end of your code to prevent the console from immediately closing upon execution completion.
Breakpoints should work now within the debugger GUI just like running in serial. All processes will be halted when hitting a breakpoint.