On 13. Jan, 2009, at 15:17, Bartlett, Roscoe A wrote:

In Trilinos, an MPI configured build creates all MPI executables (in some sense). Also, most Trilinos software is set up to automatically check to see if MPI is initialized or not and will run correctly in serial mode with MPI enabled but not initialized.

Also, most newer MPI implementations that I have used allow you to build with MPI support but never call MPI_Init(...) and never have to use mpiexec/mpirun in order to run a serial executable (as long as you don't call MPI functions). That is how you can get away with defining CMAKE_[C,CXX,Fortran]_COMPILER as the MPI compiler wrappers. Also, if you only use try_compile(...) tests at configure time, then you will never have any problem with this. Even with try_run(...), as long as these tests don't call MPI functions then they should work just fine also with most newer MPI implementations.

Lastly, our project Trilinos does not really define *any* executables except for tests and examples. To set up even single- process tests/examples to work with MPI is trivial. There is a single object that you have to create in main(...) like:

 Teuchos::GlobalMPISession mpiSession(&argc, &argv);

and you just have to run the test/example with mpirun/mpiexec with one process in case your MPI implementation requires that you do so.

The C++ class Teuchos::GlobalMPISession works with both MPI and non- MPI enabled software.

That might be true for Trilinos, but not necessarily for other projects. I can easily imagine a project where the main executable/ library is built using MPI, but some helper/utility programs are not. There is no point in linking them against MPI. This not only makes startup slower, but also increases memory footprint. In some cases it might even be harmful.



4) The standard MPI install structure of many MPI implementations
(e.g. MPICH, OpenMPI, LAM MPI etc.) of prefix/[include,
bin] will be
exploited and searching from MPI_BASE_DIR (which is set by the
client) will be done.  In this way, you can just set a single cache
variable on most systems and get MPI totally set up.

This won't work at all. See the --includedir and --libdir
options of the OpenMPI configure script. Your proposal will
force these values to the default, making too many assumptions.

You misunderstood. This would not require that MPI must be installed in PREFIX/[include, bin, lib] but if it is, then the user could just give the base directory. It is not hard to set this up at all and I am surprised that the other CMake find modules don't do this. However, if we are going to just use mpicc/mpiCC/mpiC++/ mpif77 etc and mpirun/mpiexec then we just need the 'bin' directory and can thrown the rest of this out.


It's not necessary. The user can define CMAKE_PREFIX_PATH and this has the effect you want.




These days, I don't know if anyone still uses raw compilers
and then
tries to manually pass in the compiler options and link
libraries.
We can still support such a thing but I think this is the
1% exception
instead of the rule.  Am I wrong about this?

I know of at least one large project which does not use the
wrappers because the developers abstracted the communications
into separate libraries, one for MPI, one for GAMMA and one
for LVM. The user has then the choice of which library should
be used when he starts the program. Couldn't do that with
your proposal.

Is this a runtime option or a configure-time option in this "large project"? If it is a runtime option, then you have to at least build in support for MPI so using the MPI compiler wrappers is just fine. If it is a configure-time option, then you can configure with and without MPI. That is exactly what Trilinos does. You can build a serial version of Trilinos with and without MPI. If there was some other great communication layer we could also wrap that and use that with most of Trilinos (most of Trilinos uses thin abstract adapters for communication and is not directly tied to MPI).

It is a runtime option. Before you start a solver you can choose which implementation of the communications library you want. One of the reasons I don't like linking against all possible parallel communications libraries is our heterogeneous cluster. On some compute nodes PVM is available, but not MPI and vice versa. There are also differenc MPI implementations around (OpenMPI, Quadrics, etc.) The queueing system automagically submits the job to the right queue. Problem is now, that if e.g. everything is linked against OpenMPI but is submitted to a queue where only PVM or Quadrics MPI is installed, the program won't even start.

If you really want to use an MPI compiler for everything, then you could use the following FindMpiCompilers.cmake module I came up with:

# - Find the MPI compiler wrappers
# This module locates the MPI compiler wrappers (mpicc, mpicxx/mpic++, mpif77 and mpif90). # It is useful if one wants to force a project to use the MPI compiler wrappers as default
# compilers.
#
# The module has the following COMPONENTS:
#  C    searches for mpicc
#  CXX  searches for mpicxx and mpic++
#  F77  searches for mpif77
#  F90  searches for mpif90
# If no components are specified, all of them are enabled by default.
#
# The module sets the following cache variables (if the corresponding module is enabled):
#  MPICOMPILERS_C    the mpicc compiler
#  MPICOMPILERS_CXX  the mpicxx/mpic++ compiler
#  MPICOMPILERS_F77  the mpif77 compiler
#  MPICOMPILERS_F90  the mpif90 compiler
#
# If the user wishes to specify a specific compiler wrapper (e.g. one which is # using a non-standard name or one which is not found on the path) can do so
# by setting the corresponding MPICOMPILERS_XXX variable (e.g. using the
# -D flag the first time CMake is run). It also honours environment variables # by the same name. The CC, CXX and similar variables are not considered by
# design.
#
# If the module is not REQUIRED make sure to check the MPICOMPILERS_XXX
# variables.
#
# Beware that although the module can search for both the mpif77 and mpif90 # compiler wrappers, CMake only knows the CMAKE_Fortran_COMPILER variable # which means that you can't use both of the wrappers in the same project. This,
# however, probably is not a big issue as Fortran90 is a superset of
# Fortran77 and all Fortran90 compilers I know of also process Fortran77
# sources.
#
# An example CMakeLists.txt could look like this:
#
# # prevent CMake from compiler detection using NONE as the project language
#  project( some_project NONE )
#
#  cmake_minimum_required( VERSION 2.6 )
#
#  # find the mpi compiler wrappers
#  find_package( MpiCompilers REQUIRED CXX F77 )
#
#  # set the CMAKE_XXX_COMPILER variables
#  set( CMAKE_CXX_COMPILER ${MPICOMPILERS_CXX} )
#  set( CMAKE_Fortran_COMPILER ${MPICOMPILERS_F77} )
#  # enable the corresponding languages to do the compiler detection
#  enable_language( CXX )
#  enable_language( Fortran )
#
#  # now go on as usual
#  add_executable( fancy_mpi_program source1.cxx source2.f )

# Copyright 2009 Michael Wild <[email protected]>

# check the components that are requested
if( MpiCompilers_FIND_COMPONENTS )
  set( __MpiCompilers_C FALSE )
  set( __MpiCompilers_CXX FALSE )
  set( __MpiCompilers_F77 FALSE )
  set( __MpiCompilers_F90 FALSE )
  foreach( __MpiCompilers_comp ${MpiCompilers_FIND_COMPONENTS} )
    if( __MpiCompilers_comp STREQUAL C )
      set( __MpiCompilers_C TRUE )
    elseif( __MpiCompilers_comp STREQUAL CXX )
      set( __MpiCompilers_CXX TRUE )
    elseif(__MpiCompilers_comp STREQUAL F77 )
      set( __MpiCompilers_F77 TRUE )
    elseif( __MpiCompilers_comp STREQUAL F90 )
      set( __MpiCompilers_F90 TRUE )
    else( __MpiCompilers_comp STREQUAL C )
      message( FATAL_ERROR "Unknown component ${__MpiCompilers_comp}" )
    endif( __MpiCompilers_comp STREQUAL C )
  endforeach( __MpiCompilers_comp )
else( MpiCompilers_FIND_COMPONENTS )
  # by default turn all components on
  set( __MpiCompilers_C TRUE )
  set( __MpiCompilers_CXX TRUE )
  set( __MpiCompilers_F77 TRUE )
  set( __MpiCompilers_F90 TRUE )
endif( MpiCompilers_FIND_COMPONENTS )

# find the requested compilers and set up the list
# of required variables
set( __MpiCompilers_REQVARS "" )
set( __MpiCompilers_FOUNDCOMPILERS "" )
if( __MpiCompilers_C )
  if( NOT "$ENV{MPICOMPILERS_C}" STREQUAL "" )
set( MPICOMPILERS_C $ENV{MPICOMPILERS_C} CACHE FILEPATH "Path to the MPI C compiler" )
  else( NOT "$ENV{MPICOMPILERS_C}" STREQUAL "" )
find_program( MPICOMPILERS_C mpicc DOC "Path to the MPI C compiler" )
  endif( NOT "$ENV{MPICOMPILERS_C}" STREQUAL "" )
  list( APPEND __MpiCompilers_REQVARS MPICOMPILERS_C )
set( __MpiCompilers_FOUNDCOMPILERS "$ {__MpiCompilers_FOUNDCOMPILERS} ${MPICOMPILERS_C}" )
endif( __MpiCompilers_C )
if( __MpiCompilers_CXX )
  if( NOT "$ENV{MPICOMPILERS_CXX}" STREQUAL "" )
set( MPICOMPILERS_CXX $ENV{MPICOMPILERS_CXX} CACHE FILEPATH "Path to the MPI C++ compiler" )
  else( NOT "$ENV{MPICOMPILERS_CXX}" STREQUAL "" )
find_program( MPICOMPILERS_CXX NAMES mpicxx mpic++ DOC "Path to the MPI C++ compiler" )
  endif( NOT "$ENV{MPICOMPILERS_CXX}" STREQUAL "" )
  list( APPEND __MpiCompilers_REQVARS MPICOMPILERS_CXX )
set( __MpiCompilers_FOUNDCOMPILERS "$ {__MpiCompilers_FOUNDCOMPILERS} ${MPICOMPILERS_CXX}" )
endif( __MpiCompilers_CXX )
if( __MpiCompilers_F77 )
  if( NOT "$ENV{MPICOMPILERS_F77}" STREQUAL "" )
set( MPICOMPILERS_F77 $ENV{MPICOMPILERS_F77} CACHE FILEPATH "Path to the MPI F77 compiler" )
  else( NOT "$ENV{MPICOMPILERS_F77}" STREQUAL "" )
find_program( MPICOMPILERS_F77 mpif77 DOC "Path to the MPI F77 compiler" )
  endif( NOT "$ENV{MPICOMPILERS_F77}" STREQUAL "" )
  list( APPEND __MpiCompilers_REQVARS MPICOMPILERS_F77 )
set( __MpiCompilers_FOUNDCOMPILERS "$ {__MpiCompilers_FOUNDCOMPILERS} ${MPICOMPILERS_F77}" )
endif( __MpiCompilers_F77 )
if( __MpiCompilers_F90 )
  if( NOT "$ENV{MPICOMPILERS_F90}" STREQUAL "" )
set( MPICOMPILERS_F90 $ENV{MPICOMPILERS_F90} CACHE FILEPATH "Path to the MPI F90 compiler" )
  else( NOT "$ENV{MPICOMPILERS_F90}" STREQUAL "" )
find_program( MPICOMPILERS_F90 mpif90 DOC "Path to the MPI F77 compiler" )
  endif( NOT "$ENV{MPICOMPILERS_F90}" STREQUAL "" )
  list( APPEND __MpiCompilers_REQVARS MPICOMPILERS_F90 )
set( __MpiCompilers_FOUNDCOMPILERS "$ {__MpiCompilers_FOUNDCOMPILERS} ${MPICOMPILERS_F90}" )
endif( __MpiCompilers_F90 )

mark_as_advanced( ${__MpiCompilers_REQVARS} )

# handle standard arguments
include( FindPackageHandleStandardArgs )
find_package_handle_standard_args( MpiCompilers DEFAULT_MSG __MpiCompilers_FOUNDCOMPILERS ${__MpiCompilers_REQVARS} )



The argument for directly using the MPI compiler wrappers is compelling (and that is why almost everyone I know uses them).

Yes, for simple projects. NOT for mixed projects.

Michael

Attachment: PGP.sig
Description: This is a digitally signed message part

_______________________________________________
CMake mailing list
[email protected]
http://www.cmake.org/mailman/listinfo/cmake

Reply via email to