source: pypar/mpiext.c @ 907

Last change on this file since 907 was 123, checked in by ole, 19 years ago

Files for 64 bit machine + latest Cvs version

File size: 25.2 KB
RevLine 
[85]1/************************************************************************/
2/* PyPAR - Parallel Python using MPI                                    */
3/* Copyright (C) 2001, 2002, 2003 Ole M. Nielsen                        */
4/*                                                                      */
5/* See enclosed README file for details of installation and use.        */
6/*                                                                      */   
7/* This program is free software; you can redistribute it and/or modify */
8/* it under the terms of the GNU General Public License as published by */
9/* the Free Software Foundation; either version 2 of the License, or    */
10/* (at your option) any later version.                                  */
11/*                                                                      */     
12/* This program is distributed in the hope that it will be useful,      */
13/* but WITHOUT ANY WARRANTY; without even the implied warranty of       */
14/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        */
15/* GNU General Public License (http://www.gnu.org/copyleft/gpl.html)    */
16/* for more details.                                                    */
17/*                                                                      */
18/* You should have received a copy of the GNU General Public License    */
19/* along with this program; if not, write to the Free Software          */
20/*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307*/
21/*                                                                      */
22/*                                                                      */
23/* Contact address: Ole.Nielsen@anu.edu.au                              */
24/*                                                                      */
25/* version (see __version__ in pypar.py)                                */
26/* date (see __date__ in pypar.py)                                      */
27/************************************************************************/
28
29
30#include "Python.h"
31#include "mpi.h"
32#include "math.h"
33#include "Numeric/arrayobject.h"
34
[123]35/* to handle MPI constants export (shamelessly stolen from _cursesmodule.c)*/
[85]36#define SetDictInt(string,ch) \
37        PyDict_SetItemString(ModDict, string, PyInt_FromLong((long) (ch)));
38
[123]39/* Remap struct MPI_op to int (easier to handle by python)*/
[85]40#define MAX 1
41#define MIN 2
42#define SUM 3
43#define PROD 4
44#define LAND 5
45#define BAND 6
46#define LOR 7
47#define BOR 8
48#define LXOR 9
49#define BXOR 10
50#define MAXLOC 11
51#define MINLOC 12
[123]52/*#define REPLACE 13 // Not available on all MPI systems */
[85]53
[123]54
55static char errmsg[132];  /*Used to cretae exception messages*/
56
[85]57int length(PyArrayObject *x) { 
[123]58  /*Compute the total length of contiguous array
59  /*
60  /*Necessary for communicating multi dimensional arrays */
[85]61 
62  int i, length;
63 
64  /* Compute total length of contiguous data */
65  length = 1;
66  for (i=0; i<x->nd; i++) {
67    length *= x->dimensions[i];
68  } 
69   
70  return length;
71} 
72
73
74MPI_Datatype type_map(PyArrayObject *x, int *count) { 
[123]75  /* Return the MPI Datatype corresponding to                       
76  /* the Python data type as follows 
77  /*
78  /* TYPE    py_type  mpi_type  bytes  symbol
79  /* ----------------------------------------
80  /* INT       4        6         4      'i'
81  /* LONG      5        8         8      'l'
82  /* FLOAT     6       10         4      'f' 
83  /* DOUBLE    7       11         8      'd'
84  /*
85  /* Also return the total number of elements in the array
86  /*
87  /* The Python datatype COMPLEX ('F') and COMPLEX_DOUBLE ('D')
88  /* is treated as a special case to the absence of an
89  /* MPI_COMPLEX datatype:
90  /*
91  /* Complex arrays are mapped to float or double arrays with real
92  /* and imaginary parts alternating and count is updated. */
[85]93 
94  int py_type;
95  MPI_Datatype mpi_type;
96
97  *count = length(x);
98   
99  py_type = x -> descr -> type_num;     
100  if (py_type == PyArray_DOUBLE) 
101    mpi_type = MPI_DOUBLE;
102  else if (py_type == PyArray_INT) 
103    mpi_type = MPI_INT;
104  else if (py_type == PyArray_CDOUBLE) {
105    mpi_type = MPI_DOUBLE;
106    (*count) *= 2;
107  } else if (py_type == PyArray_FLOAT) 
108    mpi_type = MPI_FLOAT;
109  else if (py_type == PyArray_LONG)   
110    mpi_type = MPI_LONG; 
111  else if (py_type == PyArray_CFLOAT) {
112    mpi_type = MPI_FLOAT;
113    (*count) *= 2;
114  } else {
115    PyErr_SetString(PyExc_ValueError, "Array must be of type int or float");
[123]116    return NULL;
[85]117  }     
118
[123]119  /*printf("Types %d %d\n", py_type, mpi_type); */
[85]120 
121  return mpi_type;
122}   
123
124
125MPI_Op op_map(int py_op) { 
126 
127  MPI_Op mpi_op;
128 
129  if (py_op == MAX) 
130    mpi_op = MPI_MAX;
131  else if (py_op == MIN)   
132    mpi_op = MPI_MIN; 
133  else if (py_op == SUM)   
134    mpi_op = MPI_SUM; 
135  else if (py_op == PROD)   
136    mpi_op = MPI_PROD; 
137  else if (py_op == LAND)   
138    mpi_op = MPI_LAND; 
139  else if (py_op == BAND)   
140    mpi_op = MPI_BAND; 
141  else if (py_op == LOR)   
142    mpi_op = MPI_LOR; 
143  else if (py_op == BOR)   
144    mpi_op = MPI_BOR; 
145  else if (py_op == LXOR)   
146    mpi_op = MPI_LXOR; 
147  else if (py_op == BXOR)   
148    mpi_op = MPI_BXOR; 
149  else if (py_op == MAXLOC)
150    mpi_op = MPI_MAXLOC;
151  else if (py_op == MINLOC)   
152    mpi_op = MPI_MINLOC; 
[123]153  /*else if (py_op == REPLACE)*/   
154  /*  mpi_op = MPI_REPLACE; */ 
[85]155  else {
156    PyErr_SetString(PyExc_ValueError, "Operation unknown");
[123]157    return NULL;
[85]158  }     
159 
160  return mpi_op;
161} 
162
163
164/*********************************************************/
165/* send_string                                           */
166/* Send string of characters                             */
167/*                                                       */
168/*********************************************************/
169static PyObject *send_string(PyObject *self, PyObject *args) {
170  char *s;
[123]171  int destination, tag, length, error, myid;
[85]172 
173  /* process the parameters */
174  if (!PyArg_ParseTuple(args, "s#ii", &s, &length, &destination, &tag))
175    return NULL;
176 
177  /* call the MPI routine */
[123]178  error = MPI_Send(s, length, MPI_CHAR, destination, tag, MPI_COMM_WORLD);
179 
180  if (error != 0) {
181    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
182    sprintf(errmsg, "Proc %d: MPI_Send failed with error code %d\n", myid, error);
183    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg */
184    return NULL;
185  } 
186     
187  return Py_BuildValue("");
[85]188}
189
190/**********************************************************/
191/* receive_string                                         */
192/* Receive string of characters                           */
193/*                                                        */
194/**********************************************************/
195static PyObject *receive_string(PyObject *self, PyObject *args) {
196  char *s;
[123]197  int source, tag, length, error, st_length, myid; 
[85]198  MPI_Status status;
199
200  /* process the parameters */
201  if (!PyArg_ParseTuple(args, "s#ii", &s, &length, &source, &tag))
202    return NULL;
203   
204  /* call the MPI routine */
[123]205  error = MPI_Recv(s, length, MPI_CHAR, source, tag, MPI_COMM_WORLD, &status);
206
207  if (error != 0) {
208    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
209    sprintf(errmsg, "Proc %d: MPI_Recv failed with error code %d\n", myid, error);
210    PyErr_SetString(PyExc_RuntimeError, errmsg);   
211    return NULL;
212  } 
213     
[85]214  MPI_Get_count(&status, MPI_CHAR, &st_length); 
[123]215  /*status.st_length is not available in all MPI implementations
216  //Alternative is: MPI_Get_elements(MPI_Status *, MPI_Datatype, int *); */
[85]217
[123]218  /*Still include error msg in status in case exception is caught. */
219  return Py_BuildValue("(iiiii)", status.MPI_SOURCE, status.MPI_TAG,
[85]220  status.MPI_ERROR, st_length, sizeof(char)); 
221}
222
223/**********************************************************/
[123]224/* broadcast_string                                           */
[85]225/* Broadcast string of characters                         */
226/*                                                        */
227/**********************************************************/
[123]228static PyObject *broadcast_string(PyObject *self, PyObject *args) {
[85]229  char *s;
[123]230  int source, length, error, myid; 
[85]231
232  /* process the parameters */
233  if (!PyArg_ParseTuple(args, "s#i", &s, &length, &source))
234    return NULL;
235   
236  /* call the MPI routine */
[123]237  error = MPI_Bcast(s, length, MPI_CHAR, source, MPI_COMM_WORLD);
238  if (error != 0) {
239    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
240    sprintf(errmsg, "Proc %d: MPI_Bcast failed with error code %d\n", myid, error);
241    PyErr_SetString(PyExc_RuntimeError, errmsg);   
242    return NULL;
243  } 
[85]244   
[123]245  return Py_BuildValue(""); 
[85]246}
247
248/**********************************************************/
249/* scatter_string                                         */
250/* Scatter string of characters                           */
251/*                                                        */
252/**********************************************************/
253static PyObject *scatter_string(PyObject *self, PyObject *args) {
254  char *s;
255  char *d;
[123]256  int source, count, error, myid, numprocs; 
[85]257
258  /* process the parameters */
259  if (!PyArg_ParseTuple(args, "s#si", &s, &count, &d, &source))
260    return NULL;
261   
[123]262  error = MPI_Comm_size(MPI_COMM_WORLD,&numprocs);   
263  count = count/numprocs;
264 
[85]265  /* call the MPI routine */
[123]266  error = MPI_Scatter(s, count, MPI_CHAR, d, count, MPI_CHAR, source, MPI_COMM_WORLD);
267
268  if (error != 0) {
269    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
270    sprintf(errmsg, "Proc %d: MPI_Scatter failed with error code %d\n", myid, error);
271    PyErr_SetString(PyExc_RuntimeError, errmsg);   
272    return NULL;
273  } 
[85]274   
[123]275  return Py_BuildValue(""); 
[85]276}
277
278/**********************************************************/
279/* gather_string                                         */
280/* Gather string of characters                           */
281/*                                                        */
282/**********************************************************/
283static PyObject *gather_string(PyObject *self, PyObject *args) {
284  char *s;
285  char *d;
[123]286  int source, error, count, myid; 
[85]287
288  /* process the parameters */
289  if (!PyArg_ParseTuple(args, "s#si", &s, &count, &d, &source))
290    return NULL;
291   
292  /* call the MPI routine */
[123]293  error = MPI_Gather(s, count, MPI_CHAR, d, count,  MPI_CHAR, source, MPI_COMM_WORLD);
294 
295  if (error != 0) {
296    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
297    sprintf(errmsg, "Proc %d: MPI_Gather failed with error code %d\n", myid, error);
298    PyErr_SetString(PyExc_RuntimeError, errmsg);   
299    return NULL;
300  } 
[85]301   
[123]302  return Py_BuildValue(""); 
[85]303}
304
305
306/**********************************************************/
307/* send_array                                             */
308/* Send Numeric array of type float, double, int, or long */
309/*                                                        */
310/**********************************************************/
311static PyObject *send_array(PyObject *self, PyObject *args) {
312  PyObject *input;
313  PyArrayObject *x;
[123]314  int destination, tag, error, count, myid;
[85]315  MPI_Datatype mpi_type;
316 
317  /* process the parameters */
318  if (!PyArg_ParseTuple(args, "Oii", &input, &destination, &tag))
319    return NULL;
320   
[123]321  /*if (!PyArg_ParseTuple(args, "Oii", &x, &destination, &tag))*/
322  /* return NULL;     */
323   
[85]324  /* Make Numeric array from general sequence type (no cost if already Numeric)*/   
325  x = (PyArrayObject *)
326    PyArray_ContiguousFromObject(input, PyArray_NOTYPE, 0, 0);
327   
328  /* Input check and determination of MPI type */         
329  mpi_type = type_map(x, &count);
330  if (!mpi_type) return NULL;
331   
332  /* call the MPI routine */
[123]333  error = MPI_Send(x->data, count, mpi_type, destination, tag,\
334                   MPI_COMM_WORLD);
[85]335  Py_DECREF(x);           
[123]336 
337  if (error != 0) {
338    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
339    sprintf(errmsg, "Proc %d: MPI_Send failed with error code %d\n", myid, error);
340    PyErr_SetString(PyExc_RuntimeError, errmsg);   
341    return NULL;
342  } 
343   
344  return Py_BuildValue(""); 
[85]345}
346
347/*************************************************************/
348/* receive_array                                             */
349/* Receive Numeric array of type float, double, int, or long */
350/*                                                           */
351/*************************************************************/
352static PyObject *receive_array(PyObject *self, PyObject *args) {
353  PyObject *input;
354  PyArrayObject *x;
[123]355  int source, tag, error, st_length, size, count, myid;
[85]356  MPI_Datatype mpi_type;
357  MPI_Status status;
358
359  /* process the parameters */
[123]360  /*if (!PyArg_ParseTuple(args, "Oii", &input, &source, &tag))*/
361  /*  return NULL;*/
[85]362   
[123]363  if (!PyArg_ParseTuple(args, "Oii", &x, &source, &tag))
364    return NULL;   
365   
[85]366  /* Make Numeric array from general sequence type (no cost if already Numeric)*/   
[123]367  /*x = (PyArrayObject *) */
368  /*  PyArray_ContiguousFromObject(input, PyArray_NOTYPE, 0, 0);*/
[85]369   
370  /* Input check and determination of MPI type */         
371  mpi_type = type_map(x, &count);
372  if (!mpi_type) return NULL; 
373     
374  /* call the MPI routine */
[123]375  error =  MPI_Recv(x->data, count, mpi_type, source, tag, \
376                    MPI_COMM_WORLD, &status);
[85]377         
[123]378  /* Do not DECREF x as it must be returned to Python*/
379         
380  if (error != 0) {
381    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
382    sprintf(errmsg, "Proc %d: MPI_Recv failed with error code %d\n", myid, error);
383    PyErr_SetString(PyExc_RuntimeError, errmsg);   
384    return NULL;
385  } 
386   
387         
[85]388  MPI_Get_count(&status, mpi_type, &st_length); 
[123]389  /* status.st_length is not available in all MPI implementations*/
390  /*Alternative is: MPI_Get_elements(MPI_Status *, MPI_Datatype, int *);*/
[85]391         
392     
[123]393  /*FIXME: This might not be watertight on all platforms */
394  /* Need C equivalent to itemsize().*/
[85]395  if (mpi_type == MPI_DOUBLE) {
[123]396    size = sizeof(double);  /*8 */
[85]397  } else if (mpi_type == MPI_LONG) {
[123]398    size = sizeof(long); /*8? */
[85]399  } else if (mpi_type == MPI_FLOAT) {
400    size = sizeof(float);
401  } else if (mpi_type == MPI_INT) {   
402    size = sizeof(int); 
403  } else {
404    size = 4; 
405  }
406   
[123]407  return Py_BuildValue("(iiiii)", status.MPI_SOURCE, status.MPI_TAG,
[85]408  status.MPI_ERROR, st_length, size); 
409}
410
411
412/*************************************************************/
[123]413/* broadcast_array                                               */
[85]414/* Broadcast Num.  array of type float, double, int, or long */
415/*                                                           */
416/*************************************************************/
[123]417static PyObject *broadcast_array(PyObject *self, PyObject *args) {
[85]418  PyArrayObject *x;
[123]419  int source, error, count, myid;
[85]420  MPI_Datatype mpi_type;
[123]421  /*MPI_Status status;*/
[85]422
423  /* process the parameters */
424  if (!PyArg_ParseTuple(args, "Oi", &x, &source))
425    return NULL;
426
427  /* Input check and determination of MPI type */         
428  mpi_type = type_map(x, &count);
429  if (!mpi_type) return NULL; 
430     
431  /* call the MPI routine */
[123]432  error =  MPI_Bcast(x->data, count, mpi_type, source, \
433                     MPI_COMM_WORLD);
434         
435         
436  if (error != 0) {
437    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
438    sprintf(errmsg, "Proc %d: MPI_Bcast failed with error code %d\n", myid, error);
439    PyErr_SetString(PyExc_RuntimeError, errmsg);   
440    return NULL;
441  } 
442         
443  return Py_BuildValue("");
[85]444}
445
446/*************************************************************/
447/* scatter_array                                             */
448/* Scatter Num.    array of type float, double, int, or long */
449/*                                                           */
450/*************************************************************/
451static PyObject *scatter_array(PyObject *self, PyObject *args) {
452  PyArrayObject *x;
453  PyArrayObject *d;
[123]454  int source, error, count, myid, numprocs;
[85]455  MPI_Datatype mpi_type;
[123]456  /*MPI_Status status; */
[85]457
458  /* process the parameters */
459  if (!PyArg_ParseTuple(args, "OOi", &x, &d, &source))
460    return NULL;
461
462  /* Input check and determination of MPI type */         
463  mpi_type = type_map(x, &count);
464  if (!mpi_type) return NULL; 
[123]465   
466  error = MPI_Comm_size(MPI_COMM_WORLD,&numprocs);   
467  count = count/numprocs; 
468 
[85]469  /* call the MPI routine */
[123]470  error = MPI_Scatter(x->data, count, mpi_type, d->data, count, mpi_type, source, \
471                      MPI_COMM_WORLD);
472         
473  if (error != 0) {
474    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
475    sprintf(errmsg, "Proc %d: MPI_Scatter failed with error code %d\n", myid, error);
476    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg*/
477    return NULL;
478  } 
[85]479     
[123]480  return Py_BuildValue("");
[85]481}
482
483
484/*************************************************************/
485/* gather_array                                              */
486/* Gather Num.     array of type float, double, int, or long */
487/*                                                           */
488/*************************************************************/
489static PyObject *gather_array(PyObject *self, PyObject *args) {
490  PyArrayObject *x;
491  PyArrayObject *d;
[123]492  int source, error, count, myid;
[85]493  MPI_Datatype mpi_type;
[123]494  /*MPI_Status status; */
[85]495
496  /* process the parameters */
497  if (!PyArg_ParseTuple(args, "OOi", &x, &d, &source))
498    return NULL;
499
500  /* Input check and determination of MPI type */         
501  mpi_type = type_map(x, &count);
502  if (!mpi_type) return NULL; 
503     
504  /* call the MPI routine */
[123]505  error =  MPI_Gather(x->data, count, mpi_type, d->data, count, mpi_type, source, \
506                      MPI_COMM_WORLD);
507
508  if (error != 0) {
509    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
510    sprintf(errmsg, "Proc %d: MPI_Gather failed with error code %d\n", myid, error);
511    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg */
512    return NULL;
513  } 
514 
515  return Py_BuildValue("");
[85]516}
517
518
519
520/*************************************************************/
521/* reduce_array                                              */
522/* Reduce Num.     array of type float, double, int, or long */
523/*                                                           */
524/*************************************************************/
525static PyObject *reduce_array(PyObject *self, PyObject *args) {
526  PyArrayObject *x;
527  PyArrayObject *d;
[123]528  int source, op, error, count, count1, myid;
[85]529  MPI_Datatype mpi_type;
[123]530  /*MPI_Status status;*/
[85]531  MPI_Op mpi_op;
532
533  /* process the parameters */
534  if (!PyArg_ParseTuple(args, "OOii", &x, &d, &op, &source))
535    return NULL;
536   
537  /* Input check and determination of MPI type */         
538  mpi_type = type_map(x, &count);
539  if (!mpi_type) return NULL; 
540  if (mpi_type != type_map(d, &count1)) {
541    printf ("Input array and buffer must be of the same type\n");
542    return Py_BuildValue("i", -666);   
543  }
544
545  if (count != count1) {
546    printf ("Input array and buffer must have same length\n");
547    return Py_BuildValue("i", -666);   
548  }
549   
550  /* Input check and determination of MPI op */ 
[123]551  /*printf("op: %d\n", op);         */
[85]552  mpi_op = op_map(op);
553  if (!mpi_op) return NULL; 
554   
555  if (op == MAXLOC || op == MINLOC) {
[123]556    /*not implemented*/
[85]557    return Py_BuildValue("i", -666);
558  }
559  else {
560  /* call the MPI routine */
[123]561  error =  MPI_Reduce(x->data, d->data, count, mpi_type, mpi_op, source, \
[85]562         MPI_COMM_WORLD);
563  }
564         
[123]565  if (error != 0) {
566    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
567    sprintf(errmsg, "Proc %d: MPI_Reduce failed with error code %d\n", myid, error);
568    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg*/
569    return NULL;
570  } 
571 
572  return Py_BuildValue("");
[85]573}
574
575/*********************************************************/
576/* MPI calls rank, size, finalize, abort                 */
577/*                                                       */
578/*********************************************************/
579
580static PyObject * rank(PyObject *self, PyObject *args) {
581  int error, myid;
582
583  error = MPI_Comm_rank(MPI_COMM_WORLD,&myid);
[123]584  if (error != 0) {
585    sprintf(errmsg, "Proc ?: MPI_Comm_rank failed with error code %d\n", error);
586    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg*/
587    return NULL;
588  } 
589 
[85]590  return Py_BuildValue("i", myid);
591}
592
593static PyObject * size(PyObject *self, PyObject *args) {
[123]594  int error, numprocs, myid; 
595 
[85]596  error = MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
[123]597  if (error != 0) {
598    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
599    sprintf(errmsg, "Proc %d: MPI_Comm_size failed with error code %d\n", myid, error);
600    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg*/
601    return NULL;
602  } 
603 
[85]604  return Py_BuildValue("i", numprocs);
605}
606 
607static PyObject * Get_processor_name(PyObject *self, PyObject *args) { 
608  char processor_name[MPI_MAX_PROCESSOR_NAME];
[123]609  int  error, namelen, myid;
[85]610
611  error = MPI_Get_processor_name(processor_name,&namelen);
[123]612  if (error != 0) {
613    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
614    sprintf(errmsg, "Proc %d: Get_processor_name failed with error code %d\n", myid, error);
615    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg*/
616    return NULL;
617  } 
618 
[85]619  return Py_BuildValue("s#", processor_name, namelen);
620}   
621
622static PyObject * init(PyObject *self, PyObject *args) { 
623  PyObject *input;
624
[123]625  int i, error, myid;
[85]626  int argc = 0; 
627  char **argv;   
628
629  /* process input parameters */
630  if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &input))
631    return NULL;
632
633  /* Reconstruct C-commandline */     
634  /*                           */ 
[123]635  argc = PyList_Size(input); /*Number of commandline arguments*/
[85]636  argv = (char**) malloc((argc+1)*sizeof(char*)); 
637 
638  for (i=0; i<argc; i++) 
639    argv[i] = PyString_AsString( PyList_GetItem(input, i) );
640   
[123]641  argv[i] = NULL; /*Lam 7.0 requires last arg to be NULL  */
[85]642 
643  error = MPI_Init(&argc, &argv); 
[123]644  if (error != 0) {
645    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
646    sprintf(errmsg, "Proc ?: MPI_Init failed with error code %d\n", error);
647    PyErr_SetString(PyExc_RuntimeError, errmsg);   
648    return NULL;
649  } 
650
651  return Py_BuildValue(""); 
[85]652} 
653
654
[123]655static PyObject * initialized(PyObject *self, PyObject *args) { 
656  int error, flag, myid;
657 
[85]658  error = MPI_Initialized(&flag);
659 
[123]660  if (error != 0) {
661    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
662    sprintf(errmsg, "Proc %d: MPI_Initialized failed with error code %d\n", myid, error);
663    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg*/
664    return NULL;
665  } 
666
[85]667  return Py_BuildValue("i", flag); 
668} 
669
670 
[123]671static PyObject * finalize(PyObject *self, PyObject *args) { 
672  int error, myid;
[85]673
[123]674  MPI_Comm_rank(MPI_COMM_WORLD, &myid); 
675 
[85]676  error = MPI_Finalize();
[123]677  if (error != 0) {
678    sprintf(errmsg, "Proc %d: MPI_Finalize failed with error code %d\n", myid, error);
679    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg*/
680    return NULL;
681  } 
682   
683  return Py_BuildValue("");
[85]684} 
685
[123]686static PyObject * mpi_abort(PyObject *self, PyObject *args) { 
687  int error, code=0, myid;
[85]688 
689  error = MPI_Abort(MPI_COMM_WORLD, code);
[123]690  if (error != 0) {
691    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
692    sprintf(errmsg, "Proc %d: MPI_Abort failed with error code %d\n", myid, error);
693    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg*/
694    return NULL;
695  } 
696 
697  return Py_BuildValue(""); 
[85]698} 
699
[123]700static PyObject * barrier(PyObject *self, PyObject *args) { 
701  int error, myid;
[85]702 
703  error = MPI_Barrier(MPI_COMM_WORLD);
[123]704  if (error != 0) {
705    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
706    sprintf(errmsg, "Proc %d: MPI_Barrier failed with error code %d\n", myid, error);
707    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg*/
708    return NULL;
709  } 
710 
711  return Py_BuildValue("");
[85]712}   
713
714static PyObject * Wtime(PyObject *self, PyObject *args) {     
715  double t;
716 
717  t = MPI_Wtime();
718  return Py_BuildValue("d", t);     
719}     
720 
[123]721 
[85]722/**********************************/
723/* Method table for python module */
724/**********************************/
725
726static struct PyMethodDef MethodTable[] = {
727  {"size", size, METH_VARARGS}, 
728  {"rank", rank, METH_VARARGS}, 
[123]729  {"barrier", barrier, METH_VARARGS},         
730  {"time", Wtime, METH_VARARGS},           
731  {"get_processor_name", Get_processor_name, METH_VARARGS},             
[85]732  {"init", init, METH_VARARGS},         
[123]733  {"initialized", initialized, METH_VARARGS},       
734  {"finalize", finalize, METH_VARARGS},       
735  {"abort", mpi_abort, METH_VARARGS},         
[85]736  {"send_string", send_string, METH_VARARGS},
737  {"receive_string", receive_string, METH_VARARGS},     
[123]738  {"broadcast_string", broadcast_string, METH_VARARGS},       
[85]739  {"scatter_string", scatter_string, METH_VARARGS},       
740  {"gather_string", gather_string, METH_VARARGS},       
741  {"send_array", send_array, METH_VARARGS},
742  {"receive_array", receive_array, METH_VARARGS},   
[123]743  {"broadcast_array", broadcast_array, METH_VARARGS},             
[85]744  {"scatter_array", scatter_array, METH_VARARGS},             
745  {"gather_array", gather_array, METH_VARARGS},             
746  {"reduce_array", reduce_array, METH_VARARGS},             
747  {NULL, NULL}
748};
749
750
751/***************************/
752/* Module initialisation   */
753/***************************/
754
755
756void initmpiext(void){
757  PyObject *m, *ModDict;
758 
759  m = Py_InitModule("mpiext", MethodTable);
760 
[123]761  /* to handle MPI symbolic constants*/
[85]762  ModDict = PyModule_GetDict(m); 
763  SetDictInt("MPI_ANY_TAG", MPI_ANY_TAG);
764  SetDictInt("MPI_TAG_UB", MPI_TAG_UB); 
765  SetDictInt("MPI_ANY_SOURCE", MPI_ANY_SOURCE);
766  SetDictInt("MAX", MAX);
767  SetDictInt("MIN", MIN);
768  SetDictInt("SUM", SUM);
769  SetDictInt("PROD", PROD);
770  SetDictInt("LAND", LAND);
771  SetDictInt("BAND", BAND);
772  SetDictInt("LOR", LOR);
773  SetDictInt("BOR", BOR);
774  SetDictInt("LXOR", LXOR);
775  SetDictInt("BXOR", BXOR);
[123]776  /*SetDictInt("MAXLOC", MAXLOC);*/
777  /*SetDictInt("MINLOC", MINLOC);*/
778  /*SetDictInt("REPLACE", REPLACE);*/
[85]779
[123]780  /*SetDictInt("MPI_COMM_WORLD", MPI_COMM_WORLD);  */
[85]781   
[123]782  import_array();     /*Necessary for handling of NumPY structures  */
[85]783}
784
785 
786 
787
Note: See TracBrowser for help on using the repository browser.