I'm part of a Computational Science course and come from a non-programming background, so please forgive me my ignorance. I'm working on a set of code in C to numerically solve the Navier Stokes equations for a Computational Fluid Dynamics course. As a part of our task, I have to write code that runs on a single processor (serially) as well as provide the choice to parallelize that same code with OpenMP and/or MPI (to utilize multiple processors, depending on user input at the beginning of run time.I was hoping for advice from the community on doing this and I have a few questions:Should I be thinking of an if/else structure for my program? (The program would need to branch towards serial code, or MPI enabled code, or OpenMP code, or a hybrid of MPI+OpenMP, and this would mean that much of the code would be duplicated).Should I construct the actions that would be duplicated to be separate functions and call these functions during run time where they are needed? (But from what I understand function calls would increase the overhead of my code in general, regardless of what choice is picked)Would there be a way to hide the pre-processor directives, or MPI-related functions (e.g. MPI_Init()) so that they would conveniently appear or disappear depending on the choice the user made at the beginning or run time?Finally, the purpose of this task is to measure the performance benefits of using serial code, vs. OpenMP, vs. MPI, vs. MPI+OpenMP. Does it make sense that I am trying to avoid code duplication since combining the code (to increase readability) would unnecessarily add overhead to my serial code? Such as MPI-related function calls, potentially many if/else conditions, which would skew the performance measurements of my serial code, versus an if/else structure at the beginning of the program which directs it down a completely separate path (as in Q1).I hope I've asked a clear question and have abided by the community's standards. Thank you kindly.(I originally asked this question on what I believe to be the general page of stackoverflow and was directed here.)https://stackoverflow.com/questions/24340121/c-openmp-mpi-serial-program
C - OpenMP, MPI, Serial Program
fluid dynamics;parallel computing;c;mpi
I think some of your issues are more important than others and some ofyour emphasis is misplaced. In pursuing overhead, you are in danger ofmaking your program unmaintainable. It is easier to write a commonprogram and direct surplus effort somewhere more interesting. I apologize for pontificating like this.If statements. From a strict programming perspective, there is noproblem having large if-else blocks in your code. If you get your coderight, what does it matter? On the other hand, if you don't get yourcode right there is an issue. With $n$ if-else blocks present, thereare something on the order of $2^n$ different paths the execution ofyour program can take. The choice of parallelism support ($4$ paths)is not the only choice your program will make. These paths can havedifferent outcomes/behaviours (and if you think not, you probablycan't be sure), which means you have to make sure each one of thosepaths is working correctly, which requires a tremendous amount oftesting.So the typical advice is to try and minimize the number of differentpaths that can be taken through your program. The fewer there are, thefewer need to be checked.Serial/OMP/MPI/OMP+MPI. Writing four different versions of the sameprogram that are all required to be functionally identical sounds tome like a daft idea. It is not impossible, but why? The extra effortof making sure they all work exactly the same is wasted. Try tomaximize the amount of code they share between each other, especiallymathematically-tricky code. Spend the extra effort on somethinginteresting instead.Overhead. In a numerically-intensive program, the overhead ofcalling a few function is absolutely tiny relative to thecomputational work, and the overhead of not needing to communicateis virtually nil. I would not worry about a few function calls. Itwould matter in a non-optimized tight inner loop, but for API callsthis is not a consideration.MPI. I don't know how to easily write a program in a way thatexactly the same program would easily compile and work both with MPIand without any MPI at all. It is probably far too much effort to tryand hide all the MPI calls with ifdefs.One way is to have two programs, MPI and non-MPI, that rely on thesame core mathematical routines. Another way is to make sure theserial version is identical to the MPI version running in a singleprocess. The only overhead here you need to take note of is theoverhead of setting up the MPI environment: you need to make sure it'snot included in any timing results for the computation, MPI or non-MPI. The overhead of communicating $0$ bytes should be nil.OpenMP. Given how much of OpenMP's parallelism is accessed throughcompiler pragmas, rather than explicit API calls, many OpenMP programswill compile with and without OpenMP support. It is also probably notworth the effort to hide OpenMP API calls with ifdefs: just run theprogram with only one thread.