@@ -28,79 +28,141 @@ static PyObject* mpi_wait(PyObject *self, PyObject *args){
2828 return Py_BuildValue (" i" ,res);
2929}
3030
31- static PyObject* mpi_allreduce (PyObject *self, PyObject *args){
32- PyObject* pyO_arr; PyObject* pyO_datatype; PyObject* pyO_op; PyObject* pyO_comm;
33- if (!PyArg_ParseTuple ( args," OOOO:mpi_allreduce" ,&pyO_arr,&pyO_datatype,&pyO_op,&pyO_comm)){
34- error (" MPI_Allreduce([...data],MPI_Datatype type,MPI_Op op,MPI_Comm out) - needs 4 params." );
35- }
36- pyORBIT_MPI_Comm* pyComm = (pyORBIT_MPI_Comm*) pyO_comm;
37- pyORBIT_MPI_Datatype* pyDatatype = (pyORBIT_MPI_Datatype*) pyO_datatype;
38- pyORBIT_MPI_Op* pyOp = (pyORBIT_MPI_Op*) pyO_op;
39- // check the data type
40- if (pyDatatype->datatype != MPI_INT && pyDatatype->datatype != MPI_DOUBLE ){
41- error (" MPI_Allreduce(...) data type could be INT or DOUBLE. STOP." );
42- }
43- // check if it is not sequence
44- int is_seq = 0 ;
45- if (PySequence_Check (pyO_arr) == 1 ){
46- is_seq = 1 ;
31+ static PyObject* allreduce_scalar_int (PyObject* obj, pyORBIT_MPI_Op* pyOp, pyORBIT_MPI_Comm* pyComm) {
32+ long v = PyLong_AsLong (obj);
33+ if (PyErr_Occurred ()) return NULL ;
34+
35+ int val = (int )v;
36+ ORBIT_MPI_Allreduce (ORBIT_MPI_IN_PLACE , &val, 1 , MPI_INT , pyOp->op , pyComm->comm );
37+ return Py_BuildValue (" i" , val);
38+ }
39+
40+ static PyObject* allreduce_scalar_double (PyObject* obj, pyORBIT_MPI_Op* pyOp, pyORBIT_MPI_Comm* pyComm) {
41+ double val = PyFloat_AsDouble (obj);
42+ if (PyErr_Occurred ()) return NULL ;
43+
44+ ORBIT_MPI_Allreduce (ORBIT_MPI_IN_PLACE , &val, 1 , MPI_DOUBLE , pyOp->op , pyComm->comm );
45+ return Py_BuildValue (" d" , val);
46+ }
47+
48+ static PyObject* allreduce_sequence_int (PyObject* obj, pyORBIT_MPI_Op* pyOp, pyORBIT_MPI_Comm* pyComm) {
49+ PyObject *seq = PySequence_Fast (obj, " MPI_Allreduce(...) expected a sequence of ints" );
50+ if (seq == NULL ) return NULL ;
51+
52+ Py_ssize_t size = PySequence_Fast_GET_SIZE (seq);
53+ PyObject *pyRes = PyTuple_New (size);
54+
55+ if (pyRes == NULL ) {
56+ Py_DECREF (seq);
57+ return NULL ;
58+ }
59+
60+ int buff_index = 0 ;
61+ int *buf = BufferStore::getBufferStore ()->getFreeIntArr (buff_index, (int )size);
62+
63+ for (Py_ssize_t i = 0 ; i < size; ++i) {
64+ long v = PyLong_AsLong (PySequence_Fast_GET_ITEM (seq, i));
65+ if (PyErr_Occurred ()) {
66+ BufferStore::getBufferStore ()->setUnusedIntArr (buff_index);
67+ Py_DECREF (pyRes);
68+ Py_DECREF (seq);
69+ return NULL ;
4770 }
48- // it is NOT SEQUENCE
49- if (is_seq == 0 ){
50- if (pyDatatype->datatype == MPI_INT ){
51- int val = (int ) PyLong_AsLong (pyO_arr);
52- int val_out = 0 ;
53- ORBIT_MPI_Allreduce (&val,&val_out,1 ,MPI_INT ,pyOp->op ,pyComm->comm );
54- return Py_BuildValue (" i" ,val_out);
55- }
56- if (pyDatatype->datatype == MPI_DOUBLE ){
57- double val = PyFloat_AsDouble (pyO_arr);
58- double val_out = 0 .;
59- ORBIT_MPI_Allreduce (&val,&val_out,1 ,MPI_DOUBLE ,pyOp->op ,pyComm->comm );
60- return Py_BuildValue (" d" ,val_out);
61- }
62- error (" MPI_Allreduce(...) - use only INT or DOUBLE data types" );
71+ buf[i] = (int )v;
72+ }
73+
74+ ORBIT_MPI_Allreduce (ORBIT_MPI_IN_PLACE , buf, (int )size, MPI_INT , pyOp->op , pyComm->comm );
75+
76+ for (Py_ssize_t i = 0 ; i < size; ++i) {
77+ PyObject *item = Py_BuildValue (" i" , buf[i]);
78+ if (item == NULL || PyTuple_SetItem (pyRes, i, item) != 0 ) {
79+ Py_XDECREF (item);
80+ BufferStore::getBufferStore ()->setUnusedIntArr (buff_index);
81+ Py_DECREF (pyRes);
82+ Py_DECREF (seq);
83+ return NULL ;
6384 }
64- // it IS A SEQUENCE
65- int size = PySequence_Size (pyO_arr);
66- PyObject* pyRes = PyTuple_New (size);
67- // data is an INT array
68- if (pyDatatype->datatype == MPI_INT ){
69- int buff_index0 = 0 ;
70- int buff_index1 = 0 ;
71- int * arr = BufferStore::getBufferStore ()->getFreeIntArr (buff_index0,size);
72- int * arr_out = BufferStore::getBufferStore ()->getFreeIntArr (buff_index1,size);
73- for (int i = 0 ; i < size; i++){
74- arr[i]= (int ) PyLong_AsLong (PySequence_Fast_GET_ITEM (pyO_arr, i));
75- }
76- ORBIT_MPI_Allreduce (arr,arr_out,size,MPI_INT ,pyOp->op ,pyComm->comm );
77- for (int i = 0 ; i < size; i++){
78- if (PyTuple_SetItem (pyRes,i,Py_BuildValue (" i" ,arr_out[i])) != 0 ){
79- error (" MPI_Allreduce(...) cannot create a resulting tuple." );
80- }
81- }
82- BufferStore::getBufferStore ()->setUnusedIntArr (buff_index0);
83- BufferStore::getBufferStore ()->setUnusedIntArr (buff_index1);
85+ }
86+
87+ BufferStore::getBufferStore ()->setUnusedIntArr (buff_index);
88+ Py_DECREF (seq);
89+ return pyRes;
90+ }
91+
92+ static PyObject* allreduce_sequence_double (PyObject* obj, pyORBIT_MPI_Op* pyOp, pyORBIT_MPI_Comm* pyComm) {
93+ PyObject *seq = PySequence_Fast (obj, " MPI_Allreduce(...) expected a sequence of ints" );
94+ if (seq == NULL ) return NULL ;
95+
96+ Py_ssize_t size = PySequence_Fast_GET_SIZE (seq);
97+ PyObject *pyRes = PyTuple_New (size);
98+
99+ if (pyRes == NULL ) {
100+ Py_DECREF (seq);
101+ return NULL ;
102+ }
103+
104+ int buff_index = 0 ;
105+ double *buf = BufferStore::getBufferStore ()->getFreeDoubleArr (buff_index, (int )size);
106+
107+ for (Py_ssize_t i = 0 ; i < size; ++i) {
108+ double v = PyFloat_AsDouble (PySequence_Fast_GET_ITEM (seq, i));
109+ if (PyErr_Occurred ()) {
110+ BufferStore::getBufferStore ()->setUnusedDoubleArr (buff_index);
111+ Py_DECREF (pyRes);
112+ Py_DECREF (seq);
113+ return NULL ;
84114 }
85- // data is an DOUBLE array
86- if (pyDatatype->datatype == MPI_DOUBLE ){
87- int buff_index0 = 0 ;
88- int buff_index1 = 0 ;
89- double * arr = BufferStore::getBufferStore ()->getFreeDoubleArr (buff_index0,size);
90- double * arr_out = BufferStore::getBufferStore ()->getFreeDoubleArr (buff_index1,size);
91- for (int i = 0 ; i < size; i++){
92- arr[i]= PyFloat_AsDouble (PySequence_Fast_GET_ITEM (pyO_arr, i));
93- }
94- ORBIT_MPI_Allreduce (arr,arr_out,size,MPI_DOUBLE ,pyOp->op ,pyComm->comm );
95- for (int i = 0 ; i < size; i++){
96- if (PyTuple_SetItem (pyRes,i,Py_BuildValue (" d" ,arr_out[i])) != 0 ){
97- error (" MPI_Allreduce(...) cannot create a resulting tuple." );
98- }
99- }
100- BufferStore::getBufferStore ()->setUnusedDoubleArr (buff_index0);
101- BufferStore::getBufferStore ()->setUnusedDoubleArr (buff_index1);
115+ buf[i] = v;
116+ }
117+
118+ ORBIT_MPI_Allreduce (ORBIT_MPI_IN_PLACE , buf, (int )size, MPI_DOUBLE , pyOp->op , pyComm->comm );
119+
120+ for (Py_ssize_t i = 0 ; i < size; ++i) {
121+ PyObject *item = Py_BuildValue (" d" , buf[i]);
122+ if (item == NULL || PyTuple_SetItem (pyRes, i, item) != 0 ) {
123+ Py_XDECREF (item);
124+ BufferStore::getBufferStore ()->setUnusedDoubleArr (buff_index);
125+ Py_DECREF (pyRes);
126+ Py_DECREF (seq);
127+ return NULL ;
102128 }
103- return pyRes;
129+ }
130+
131+ BufferStore::getBufferStore ()->setUnusedDoubleArr (buff_index);
132+ Py_DECREF (seq);
133+ return pyRes;
134+ }
135+
136+ static PyObject* mpi_allreduce (PyObject *self, PyObject *args){
137+ PyObject *pyO_arr, *pyO_datatype, *pyO_op, *pyO_comm;
138+
139+ if (!PyArg_ParseTuple (args," OOOO:mpi_allreduce" , &pyO_arr, &pyO_datatype, &pyO_op, &pyO_comm)) {
140+ error (" MPI_Allreduce([...data],MPI_Datatype type,MPI_Op op,MPI_Comm out) - needs 4 params." );
141+ }
142+
143+ pyORBIT_MPI_Comm* pyComm = (pyORBIT_MPI_Comm*) pyO_comm;
144+ pyORBIT_MPI_Datatype* pyDatatype = (pyORBIT_MPI_Datatype*) pyO_datatype;
145+ pyORBIT_MPI_Op* pyOp = (pyORBIT_MPI_Op*) pyO_op;
146+
147+ // check the data type
148+ MPI_Datatype dtype = pyDatatype->datatype ;
149+
150+ if (dtype != MPI_INT && dtype != MPI_DOUBLE ){
151+ error (" MPI_Allreduce(...) data type should be INT or DOUBLE. STOP." );
152+ }
153+
154+ // check if it is a sequence or a scalar
155+ if (PySequence_Check (pyO_arr) == 0 ) {
156+ if (dtype == MPI_INT ) {
157+ return allreduce_scalar_int (pyO_arr, pyOp, pyComm);
158+ }
159+ return allreduce_scalar_double (pyO_arr, pyOp, pyComm);
160+ } else {
161+ if (dtype == MPI_INT ) {
162+ return allreduce_sequence_int (pyO_arr, pyOp, pyComm);
163+ }
164+ return allreduce_sequence_double (pyO_arr, pyOp, pyComm);
165+ }
104166}
105167
106168static PyObject* mpi_bcast (PyObject *self, PyObject *args){
0 commit comments