Boost logo

Boost Users :

From: Douglas Gregor (doug.gregor_at_[hidden])
Date: 2006-12-13 13:26:21


On Thu, 2006-12-14 at 10:34 +0000, Bo Peng wrote:
> Dear boost users,
>
> I am using Boost.MPI for a python module so there is no argc, argv
> that can be provided to
>
> boost::parallel::mpi::environment(int & argc, char ** & argv)
>
> Because an environment object has to exist during the life time of the
> module, I have to define a global variable in an awkward way:
>
> int fake_argc = 0;
> char * fake_argv = "";
> char ** ptr_argv = &fake_argv;
> boost::parallel::mpi::environment env(fake_argc, ptr_argv);
>
> Can a default constructor be provided?

Unfortunately, the default constructor could only be provided if the
underlying MPI implementation is MPI-2 complaint, since MPI-1 allows MPI
implementations to require that the "argc" and "argv" pointers passed to
MPI_Init be the "real" argc and argv. I don't know what MPI
implementations take advantage of this latitude.

Boost.MPI's own Python module jumps through some hoops to be MPI-1
compliant in this regard. We basically extract the Python "sys.argv"
like this:

    object sys = object(handle<>(PyImport_ImportModule("sys")));
    mpi_init(extract<list>(sys.attr("argv")), true);

Then, we convert that into C-style argc/argv to initialize Boost.MPI's
"environment" variable. If MPI_Init does anything to that argc/argv, we
write the results back into Python's sys.argv. This routine (from
libs/parallel/src/mpi/python/py_environment.cpp) does the trick:

bool mpi_init(list python_argv, bool abort_on_exception)
{
  // If MPI is already initialized, do nothing.
  if (environment::initialized())
    return false;

  // Convert Python argv into C-style argc/argv.
  int my_argc = extract<int>(python_argv.attr("__len__")());
  char** my_argv = new char*[my_argc];
  for (int arg = 0; arg < my_argc; ++arg)
    my_argv[arg] = strdup(extract<const char*>(python_argv[arg]));

  // Initialize MPI
  int mpi_argc = my_argc;
  char** mpi_argv = my_argv;
  env = new environment(mpi_argc, mpi_argv, abort_on_exception);

  // If anything changed, convert C-style argc/argv into Python argv
  if (mpi_argv != my_argv)
    PySys_SetArgv(mpi_argc, mpi_argv);

  for (int arg = 0; arg < my_argc; ++arg)
    free(my_argv[arg]);
  delete [] my_argv;

  return true;
}

It's messy, but as far as I know that's the only way to do it for MPI-1.

I'll be happy to provide the default constructor, but it will only be
available when we can be sure that it can be implemented correctly,
either because we've checked out a particular MPI implementation (e.g.,
LAM-MPI does not need the real argc/argv) or it claims to be MPI-2
compliant. I'll add a new macro "BOOST_MPI_HAS_DEFAULT_ENVIRONMENT" that
is used to indicate that the default constructor exists.

  Cheers,
  Doug


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net