Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

mpi_eman.c

Go to the documentation of this file.
00001 // mpi_eman.c - Steve Ludtke 11/23/2010
00002 
00003 // Simple MPI bindings for Python for use with EMAN2
00004 
00005 #include <Python.h>
00006 #include <math.h>
00007 #include <mpi.h>
00008 
00009 /*
00010 Calls MPI_Init and returns the current task's rank, and the group size
00011 */
00012 static PyObject *mpi_init(PyObject *self,PyObject *args) {
00013 MPI_Init(NULL,NULL);
00014 
00015 int myrank;
00016 MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
00017 
00018 int size;
00019 MPI_Comm_size (MPI_COMM_WORLD, &size);
00020 
00021 return Py_BuildValue("ii",myrank,size);
00022 }
00023 
00024 static PyObject *mpi_comm_rank(PyObject *self,PyObject *args) {
00025 int myrank;
00026 MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
00027 
00028 return Py_BuildValue("i",myrank);
00029 }
00030 
00031 static PyObject *mpi_comm_size(PyObject *self,PyObject *args) {
00032 int size;
00033 MPI_Comm_size(MPI_COMM_WORLD, &size);
00034 
00035 return Py_BuildValue("i",size);         
00036 }
00037 
00038 /*
00039 Calls MPI_Send. Expects (string,dest rank(int),tag (int))
00040 Note that if tag is negative, receiver will not be constrained to the specific tag.
00041 */
00042 static PyObject *mpi_send(PyObject *self,PyObject *args) {
00043 const char * data;
00044 int datalen,dest,tag;
00045 
00046 // Get a string argument
00047 if (!PyArg_ParseTuple(args,"s#ii",&data,&datalen,&dest,&tag)) return NULL;
00048 
00049 MPI_Send((void *)data,datalen,MPI_CHAR,dest,tag,MPI_COMM_WORLD);
00050 
00051         Py_RETURN_NONE;
00052 
00053 }
00054 
00055 /*
00056 Calls MPI_Recv. Expects (source rank(int),tag). 
00057 If negative, ANY source/tag will be acceptable
00058 Returns (data,source rank,tag)
00059 */
00060 static PyObject *mpi_recv(PyObject *self,PyObject *args) {
00061 MPI_Status status;
00062 const char * data;
00063 int datalen,src,tag;
00064 
00065 // Get a string argument
00066 if (!PyArg_ParseTuple(args,"ii",&src,&tag)) return NULL;
00067 
00068 if (src<0) src=MPI_ANY_SOURCE;
00069 if (tag<0) tag=MPI_ANY_TAG;
00070 
00071 MPI_Probe(src,tag,MPI_COMM_WORLD,&status);
00072 
00073 MPI_Get_count(&status,MPI_CHAR,&datalen);
00074 data=(const char *)malloc(datalen);
00075 MPI_Recv((void *)data,datalen,MPI_CHAR,src,tag,MPI_COMM_WORLD,&status);
00076 
00077 PyObject *ret = Py_BuildValue("s#ii",(void *)data,datalen,status.MPI_SOURCE,status.MPI_TAG);
00078 free((void *)data);
00079 
00080 return ret;
00081 }
00082 
00083 /*
00084 Calls MPI_Probe. Expects (source rank(int),tag). 
00085 If negative, ANY source/tag will be acceptable
00086 Returns (length,source rank,tag)
00087 
00088 Useful for waiting for input from an unknown source
00089 */
00090 static PyObject *mpi_probe(PyObject *self,PyObject *args) {
00091 MPI_Status status;
00092 int datalen,src,tag;
00093 
00094 // Get a string argument
00095 if (!PyArg_ParseTuple(args,"ii",&src,&tag)) return NULL;
00096 
00097 if (src<0) src=MPI_ANY_SOURCE;
00098 if (tag<0) tag=MPI_ANY_TAG;
00099 
00100 MPI_Probe(src,tag,MPI_COMM_WORLD,&status);
00101 MPI_Get_count(&status,MPI_CHAR,&datalen);
00102 
00103 PyObject *ret = Py_BuildValue("iii",datalen,status.MPI_SOURCE,status.MPI_TAG);
00104 
00105 return ret;
00106 }
00107 
00108 /*
00109 Calls MPI_Iprobe (nonblocking). Expects (source rank(int),tag). 
00110 If negative, ANY source/tag will be acceptable
00111 Returns (length,source rank,tag)
00112 
00113 Returns None immediately if no suitable receives are pending
00114 */
00115 static PyObject *mpi_iprobe(PyObject *self,PyObject *args) {
00116 MPI_Status status;
00117 int datalen,src,tag,flag;
00118 
00119 // Get a string argument
00120 if (!PyArg_ParseTuple(args,"ii",&src,&tag)) return NULL;
00121 
00122 if (src<0) src=MPI_ANY_SOURCE;
00123 if (tag<0) tag=MPI_ANY_TAG;
00124 
00125 MPI_Iprobe(src,tag,MPI_COMM_WORLD,&flag,&status);
00126 if (!flag) Py_RETURN_NONE;
00127 
00128 MPI_Get_count(&status,MPI_CHAR,&datalen);
00129 
00130 PyObject *ret = Py_BuildValue("iii",datalen,status.MPI_SOURCE,status.MPI_TAG);
00131 
00132 return ret;
00133 }
00134 
00135 
00136 /* Calls MPI_Bcast
00137  * Different args on source and destinations. 
00138  * On source, pass in a string to transmit.
00139  * On destinations, pass in the data length and source rank.
00140  * The destinations must know the length before transmission. ALL nodes in the group must call this function
00141  * before it will complete.
00142 */
00143 static PyObject *mpi_bcast_send(PyObject *self,PyObject *args) {
00144         const char * data;
00145         int datalen;
00146         int myrank;
00147         MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
00148 
00149         PyArg_ParseTuple(args,"s#",&data,&datalen);
00150 //                      printf("Sent: %d\n",datalen);
00151         MPI_Bcast((void *)data,datalen,MPI_CHAR,myrank,MPI_COMM_WORLD);
00152         Py_RETURN_NONE;
00153 }
00154 
00155 /* Calls MPI_Bcast
00156  * Different args on source and destinations. 
00157  * On source, pass in a string to transmit.
00158  * On destinations, pass in the data length and source rank.
00159  * The destinations must know the length before transmission. ALL nodes in the group must call this function
00160  * before it will complete.
00161 */
00162 static PyObject *mpi_bcast_recv(PyObject *self,PyObject *args) {
00163         const char * data;
00164         int datalen;
00165         int root;
00166 
00167         PyArg_ParseTuple(args,"ii",&datalen,&root);
00168         data=(const char *)malloc(datalen);
00169         MPI_Bcast((void *)data,datalen,MPI_CHAR,root,MPI_COMM_WORLD);
00170 
00171         PyObject *ret = Py_BuildValue("s#",(void *)data,datalen);
00172         free((void *)data);
00173 
00174         return ret;
00175 }
00176 
00177 
00178 static PyObject * mpi_barrier(PyObject *self,PyObject *args) {
00179 
00180         MPI_Barrier(MPI_COMM_WORLD);
00181         Py_RETURN_NONE;
00182 }
00183 
00184 static PyObject * mpi_finalize(PyObject *self,PyObject *args) {
00185         MPI_Finalize();
00186         Py_RETURN_NONE;
00187 }
00188 
00189 static PyMethodDef EmanMpiMethods[] = {
00190         {"mpi_init",mpi_init,METH_VARARGS,"MPI_Init command. No arguments. Returns the rank id and process count to each node."},
00191         {"mpi_comm_rank",mpi_comm_rank,METH_VARARGS,"This will return the rank id, same as returned by mpi_init."},
00192         {"mpi_comm_size",mpi_comm_size,METH_VARARGS,"This will return the number of processes, same as returned by mpi_init."},
00193         {"mpi_send",mpi_send,METH_VARARGS,"MPI_Send(string,destination rank,tag)"},
00194         {"mpi_recv",mpi_recv,METH_VARARGS,"MPI_Recv(source rank,tag). If either is negative, arbitrary values accepted. Returns (data,src,tag)."},
00195         {"mpi_probe",mpi_probe,METH_VARARGS,"MPI_Probe(source rank,tag). If either is negative, arbitrary values accepted. Returns (len,src,tag)."},
00196         {"mpi_iprobe",mpi_iprobe,METH_VARARGS,"MPI_Iprobe(source rank,tag). If either is negative, arbitrary values accepted. Returns (len,src,tag) or None if no recieves are pending."},
00197         {"mpi_bcast_send",mpi_bcast_send,METH_VARARGS,"MPI_Bcast(string). Provide a string to broadcast to other nodes"},
00198         {"mpi_bcast_recv",mpi_bcast_recv,METH_VARARGS,"MPI_Bcast(data_length,source). Receives a broadcast of length data_length from source and returns a string."},
00199         {"mpi_barrier",mpi_barrier,METH_VARARGS,"MPI_Barrier(). No arguments or return. Blocks until all nodes call it."},
00200         {"mpi_finalize",mpi_finalize,METH_VARARGS,"MPI_Finalize(). No arguments or return. Call before exiting an MPI Python program exactly once."},
00201         {NULL,NULL,0,NULL}
00202 };
00203 
00204 PyMODINIT_FUNC initmpi_eman_c(void) {
00205         (void) Py_InitModule("mpi_eman_c", EmanMpiMethods);
00206 }
00207         

Generated on Tue Jun 11 13:40:39 2013 for EMAN2 by  doxygen 1.3.9.1