在 boost.python 中封装 MPI
Wrapping MPI in boost.python
我已经设法使用 Boost.python 编写包装器来初始化和完成 MPI 环境,但我不确定是否一切都已正确初始化。我还没有 运行 遇到任何问题,但我想看看我正在做的事情是否不正确并且会在以后引起问题,或者是否有更好的方法来做到这一点。
我知道 python 确实绑定了 MPI(通过 mpi4py),但这不能很好地满足我的需要。下面的简单示例可以用 mpi4py 代替,但我实际上不需要初始化普通 MPI 环境:我需要初始化一个专门的 MPI 环境 (MADNESS/TiledArray),其中没有 python我能找到的绑定。
我的文件结构如下:
interface.cxx:
#include <iostream>
#include <boost/python.hpp>
#include <mpi.h>
void initMPI(int argc, boost::python::list argv){
char ** argv_ = new char *[argc];
for(auto i = 0; i < argc; i++){
std::string str = boost::python::extract<std::string>(argv[i]);
auto len = str.length();
argv_[i] = new char[len+1];
strncpy(argv_[i],&str[0],len);
argv_[i][len] = '[=11=]'; // Termination character
}
MPI_Init(&argc,&argv_);
for(auto i = 0; i < argc; i++){
delete [] argv_[i];
}
delete [] argv_;
};
void finalizeMPI(){
MPI_Finalize();
};
void hello(){
int world_size, rank, name_len;
std::string name;
name.reserve(MPI_MAX_PROCESSOR_NAME);
MPI_Comm_size(MPI_COMM_WORLD,&world_size);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Get_processor_name(&name[0],&name_len);
printf("Hello world from processor %s, rank %d"
" out of %d processors\n",
name.c_str(), rank, world_size);
};
BOOST_PYTHON_MODULE(mpiinterface){
boost::python::def("init", initMPI);
boost::python::def("finalize", finalizeMPI);
boost::python::def("hello",hello);
};
test.py:
import sys,os
sys.path.append('/home/dbwy/devel/tests/MPI/boost.python')
import mpiinterface
mpiinterface.init(len(sys.argv),sys.argv)
mpiinterface.hello();
mpiinterface.finalize();
编译后,它确实给了我正确的输出:
[dbwy@medusa boost.python]$ mpirun -np 4 python test.py
Hello world from processor medusa.chem.washington.edu, rank 0 out of 4 processors
Hello world from processor medusa.chem.washington.edu, rank 3 out of 4 processors
Hello world from processor medusa.chem.washington.edu, rank 1 out of 4 processors
Hello world from processor medusa.chem.washington.edu, rank 2 out of 4 processors
真的这么简单吗?还是我错过了一些以后会造成灾难性后果的大事?
由于现在几乎所有现有的 MPI 实现都符合 1998 年发布的 MPI-2 规范,因此根本不需要对参数列表进行整个处理。从 MPI-2 开始,可以通过调用 MPI_Init(NULL, NULL)
.
来初始化 MPI
事实上,使用 MPI 就像在应用程序开始时调用 MPI_Init
一次 和 MPI_Finalize
一次 在它退出之前。如果您的程序是多线程的,那么您应该将 MPI_Init
替换为 MPI_Init_thread
并确保 MPI 库支持所需的多线程级别。
我已经设法使用 Boost.python 编写包装器来初始化和完成 MPI 环境,但我不确定是否一切都已正确初始化。我还没有 运行 遇到任何问题,但我想看看我正在做的事情是否不正确并且会在以后引起问题,或者是否有更好的方法来做到这一点。
我知道 python 确实绑定了 MPI(通过 mpi4py),但这不能很好地满足我的需要。下面的简单示例可以用 mpi4py 代替,但我实际上不需要初始化普通 MPI 环境:我需要初始化一个专门的 MPI 环境 (MADNESS/TiledArray),其中没有 python我能找到的绑定。
我的文件结构如下:
interface.cxx:
#include <iostream>
#include <boost/python.hpp>
#include <mpi.h>
void initMPI(int argc, boost::python::list argv){
char ** argv_ = new char *[argc];
for(auto i = 0; i < argc; i++){
std::string str = boost::python::extract<std::string>(argv[i]);
auto len = str.length();
argv_[i] = new char[len+1];
strncpy(argv_[i],&str[0],len);
argv_[i][len] = '[=11=]'; // Termination character
}
MPI_Init(&argc,&argv_);
for(auto i = 0; i < argc; i++){
delete [] argv_[i];
}
delete [] argv_;
};
void finalizeMPI(){
MPI_Finalize();
};
void hello(){
int world_size, rank, name_len;
std::string name;
name.reserve(MPI_MAX_PROCESSOR_NAME);
MPI_Comm_size(MPI_COMM_WORLD,&world_size);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Get_processor_name(&name[0],&name_len);
printf("Hello world from processor %s, rank %d"
" out of %d processors\n",
name.c_str(), rank, world_size);
};
BOOST_PYTHON_MODULE(mpiinterface){
boost::python::def("init", initMPI);
boost::python::def("finalize", finalizeMPI);
boost::python::def("hello",hello);
};
test.py:
import sys,os
sys.path.append('/home/dbwy/devel/tests/MPI/boost.python')
import mpiinterface
mpiinterface.init(len(sys.argv),sys.argv)
mpiinterface.hello();
mpiinterface.finalize();
编译后,它确实给了我正确的输出:
[dbwy@medusa boost.python]$ mpirun -np 4 python test.py
Hello world from processor medusa.chem.washington.edu, rank 0 out of 4 processors
Hello world from processor medusa.chem.washington.edu, rank 3 out of 4 processors
Hello world from processor medusa.chem.washington.edu, rank 1 out of 4 processors
Hello world from processor medusa.chem.washington.edu, rank 2 out of 4 processors
真的这么简单吗?还是我错过了一些以后会造成灾难性后果的大事?
由于现在几乎所有现有的 MPI 实现都符合 1998 年发布的 MPI-2 规范,因此根本不需要对参数列表进行整个处理。从 MPI-2 开始,可以通过调用 MPI_Init(NULL, NULL)
.
事实上,使用 MPI 就像在应用程序开始时调用 MPI_Init
一次 和 MPI_Finalize
一次 在它退出之前。如果您的程序是多线程的,那么您应该将 MPI_Init
替换为 MPI_Init_thread
并确保 MPI 库支持所需的多线程级别。