Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
672a5f8fbacf1cda9e8df01ceeeaf6fe4784f9c4
[simgrid.git] / src / smpi / smpi_mpi_dt.c
1 /* $Id$tag */
2
3 /* smpi_mpi_dt.c -- MPI primitives to handle datatypes                        */
4  
5 /* Note: a very incomplete implementation                                     */
6
7 /* Copyright (c) 2009 Stephane Genaud.                                        */
8 /* All rights reserved.                                                       */
9
10 /* This program is free software; you can redistribute it and/or modify it
11  *  * under the terms of the license (GNU LGPL) which comes with this package. */
12
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17
18 #include "private.h"
19 #include "smpi_mpi_dt_private.h"
20
21 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_mpi_dt, smpi,
22                                 "Logging specific to SMPI (datatype)");
23
24 typedef struct s_smpi_mpi_datatype {
25   size_t size;
26   MPI_Aint lb;
27   MPI_Aint ub;
28   int flags;
29 } s_smpi_mpi_datatype_t;
30
31 #define CREATE_MPI_DATATYPE(name, type)       \
32   static s_smpi_mpi_datatype_t mpi_##name = { \
33     sizeof(type),  /* size */                 \
34     0,             /* lb */                   \
35     sizeof(type),  /* ub = lb + size */       \
36     DT_FLAG_BASIC  /* flags */                \
37   };                                          \
38   MPI_Datatype name = &mpi_##name;
39
40
41 //The following are datatypes for the MPI functions MPI_MAXLOC and MPI_MINLOC.
42 typedef struct { float       value; int index;} float_int;
43 typedef struct { long        value; int index;} long_int ; 
44 typedef struct { double      value; int index;} double_int;
45 typedef struct { short       value; int index;} short_int;
46 typedef struct { int         value; int index;} int_int;
47 typedef struct { long double value; int index;} long_double_int; 
48
49 // Predefined data types
50 CREATE_MPI_DATATYPE(MPI_CHAR,                  char);
51 CREATE_MPI_DATATYPE(MPI_SHORT,                 short);
52 CREATE_MPI_DATATYPE(MPI_INT,                   int);
53 CREATE_MPI_DATATYPE(MPI_LONG,                  long);
54 CREATE_MPI_DATATYPE(MPI_LONG_LONG,             long long);
55 CREATE_MPI_DATATYPE(MPI_SIGNED_CHAR,           signed char);
56 CREATE_MPI_DATATYPE(MPI_UNSIGNED_CHAR,         unsigned char);
57 CREATE_MPI_DATATYPE(MPI_UNSIGNED_SHORT,        unsigned short);
58 CREATE_MPI_DATATYPE(MPI_UNSIGNED,              unsigned int);
59 CREATE_MPI_DATATYPE(MPI_UNSIGNED_LONG,         unsigned long);
60 CREATE_MPI_DATATYPE(MPI_UNSIGNED_LONG_LONG,    unsigned long long);
61 CREATE_MPI_DATATYPE(MPI_FLOAT,                 float);
62 CREATE_MPI_DATATYPE(MPI_DOUBLE,                double);
63 CREATE_MPI_DATATYPE(MPI_LONG_DOUBLE,           long double);
64 CREATE_MPI_DATATYPE(MPI_WCHAR,                 wchar_t);
65 CREATE_MPI_DATATYPE(MPI_C_BOOL,                _Bool);
66 CREATE_MPI_DATATYPE(MPI_INT8_T,                int8_t);
67 CREATE_MPI_DATATYPE(MPI_INT16_T,               int16_t);
68 CREATE_MPI_DATATYPE(MPI_INT32_T,               int32_t);
69 CREATE_MPI_DATATYPE(MPI_INT64_T,               int64_t);
70 CREATE_MPI_DATATYPE(MPI_UINT8_T,               uint8_t);
71 CREATE_MPI_DATATYPE(MPI_UINT16_T,              uint16_t);
72 CREATE_MPI_DATATYPE(MPI_UINT32_T,              uint32_t);
73 CREATE_MPI_DATATYPE(MPI_UINT64_T,              uint64_t);
74 CREATE_MPI_DATATYPE(MPI_C_FLOAT_COMPLEX,       float _Complex);
75 CREATE_MPI_DATATYPE(MPI_C_DOUBLE_COMPLEX,      double _Complex);
76 CREATE_MPI_DATATYPE(MPI_C_LONG_DOUBLE_COMPLEX, long double _Complex);
77 CREATE_MPI_DATATYPE(MPI_AINT,                  MPI_Aint);
78 CREATE_MPI_DATATYPE(MPI_OFFSET,                MPI_Offset);
79
80 CREATE_MPI_DATATYPE(MPI_FLOAT_INT,                float_int);
81
82
83 size_t smpi_datatype_size(MPI_Datatype datatype) {
84   return datatype->size;
85 }
86
87 MPI_Aint smpi_datatype_lb(MPI_Datatype datatype) {
88   return datatype->lb;
89 }
90
91 MPI_Aint smpi_datatype_ub(MPI_Datatype datatype) {
92   return datatype->ub;
93 }
94
95 int smpi_datatype_extent(MPI_Datatype datatype, MPI_Aint* lb, MPI_Aint * extent) {
96   int retval;
97
98   if((datatype->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED) {
99     retval = MPI_ERR_TYPE;
100   } else {
101     *lb =  datatype->lb;
102     *extent =  datatype->ub - datatype->lb;
103     retval = MPI_SUCCESS;
104   }
105   return MPI_SUCCESS;
106 }
107
108 int smpi_datatype_copy(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype) {
109   int retval, count;
110
111   /* First check if we really have something to do */
112   if(recvcount == 0) {
113     retval = sendcount == 0 ? MPI_SUCCESS : MPI_ERR_TRUNCATE;
114   } else if(sendtype == recvtype) {
115     /* If same datatypes used, just copy. */
116    count = sendcount < recvcount ? sendcount : recvcount;
117    memcpy(recvbuf, sendbuf, smpi_datatype_size(sendtype) * count);
118    retval = sendcount > recvcount ? MPI_ERR_TRUNCATE : MPI_SUCCESS;
119  } else {
120    /* FIXME:  cases 
121     * - If receive packed. 
122     * - If send packed
123     * to be treated once we have the MPI_Pack things ...
124     **/
125    retval = MPI_SUCCESS;
126  }
127  return retval;
128 }
129
130 typedef struct s_smpi_mpi_op {
131   MPI_User_function* func;
132 } s_smpi_mpi_op_t;
133
134 #define MAX_OP(a, b)  (b) = (a) < (b) ? (b) : (a)
135 #define MIN_OP(a, b)  (b) = (a) < (b) ? (a) : (b)
136 #define SUM_OP(a, b)  (b) += (a)
137 #define PROD_OP(a, b) (b) *= (a)
138 #define LAND_OP(a, b) (b) = (a) && (b)
139 #define LOR_OP(a, b)  (b) = (a) || (b)
140 #define LXOR_OP(a, b) (b) = (!(a) && (b)) || ((a) && !(b))
141 #define BAND_OP(a, b) (b) &= (a)
142 #define BOR_OP(a, b)  (b) |= (a)
143 #define BXOR_OP(a, b) (b) ^= (a)
144 #define MAXLOC_OP(a, b)  (b) = (a.value) < (b.value) ? (b) : (a)
145 #define MINLOC_OP(a, b)  (b) = (a.value) < (b.value) ? (a) : (b)
146 //TODO : MINLOC & MAXLOC
147
148 #define APPLY_FUNC(a, b, length, type, func) \
149   {                                          \
150     int i;                                   \
151     type* x = (type*)(a);                    \
152     type* y = (type*)(b);                    \
153     for(i = 0; i < *(length); i++) {         \
154       func(x[i], y[i]);                      \
155     }                                        \
156   }
157
158 static void max_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
159   if(*datatype == MPI_SHORT) {
160     APPLY_FUNC(a, b, length, short, MAX_OP);
161   } else if(*datatype == MPI_INT) {
162     APPLY_FUNC(a, b, length, int, MAX_OP);
163   } else if(*datatype == MPI_LONG) {
164     APPLY_FUNC(a, b, length, long, MAX_OP);
165   } else if(*datatype == MPI_UNSIGNED_SHORT) {
166     APPLY_FUNC(a, b, length, unsigned short, MAX_OP);
167   } else if(*datatype == MPI_UNSIGNED) {
168     APPLY_FUNC(a, b, length, unsigned int, MAX_OP);
169   } else if(*datatype == MPI_UNSIGNED_LONG) {
170     APPLY_FUNC(a, b, length, unsigned long, MAX_OP);
171   } else if(*datatype == MPI_FLOAT) {
172     APPLY_FUNC(a, b, length, float, MAX_OP);
173   } else if(*datatype == MPI_DOUBLE) {
174     APPLY_FUNC(a, b, length, double, MAX_OP);
175   } else if(*datatype == MPI_LONG_DOUBLE) {
176     APPLY_FUNC(a, b, length, long double, MAX_OP);
177   }
178 }
179  
180 static void min_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
181   if(*datatype == MPI_SHORT) {
182     APPLY_FUNC(a, b, length, short, MIN_OP);
183   } else if(*datatype == MPI_INT) {
184     APPLY_FUNC(a, b, length, int, MIN_OP);
185   } else if(*datatype == MPI_LONG) {
186     APPLY_FUNC(a, b, length, long, MIN_OP);
187   } else if(*datatype == MPI_UNSIGNED_SHORT) {
188     APPLY_FUNC(a, b, length, unsigned short, MIN_OP);
189   } else if(*datatype == MPI_UNSIGNED) {
190     APPLY_FUNC(a, b, length, unsigned int, MIN_OP);
191   } else if(*datatype == MPI_UNSIGNED_LONG) {
192     APPLY_FUNC(a, b, length, unsigned long, MIN_OP);
193   } else if(*datatype == MPI_FLOAT) {
194     APPLY_FUNC(a, b, length, float, MIN_OP);
195   } else if(*datatype == MPI_DOUBLE) {
196     APPLY_FUNC(a, b, length, double, MIN_OP);
197   } else if(*datatype == MPI_LONG_DOUBLE) {
198     APPLY_FUNC(a, b, length, long double, MIN_OP);
199   }
200 }
201  
202 static void sum_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
203   if(*datatype == MPI_SHORT) {
204     APPLY_FUNC(a, b, length, short, SUM_OP);
205   } else if(*datatype == MPI_INT) {
206     APPLY_FUNC(a, b, length, int, SUM_OP);
207   } else if(*datatype == MPI_LONG) {
208     APPLY_FUNC(a, b, length, long, SUM_OP);
209   } else if(*datatype == MPI_UNSIGNED_SHORT) {
210     APPLY_FUNC(a, b, length, unsigned short, SUM_OP);
211   } else if(*datatype == MPI_UNSIGNED) {
212     APPLY_FUNC(a, b, length, unsigned int, SUM_OP);
213   } else if(*datatype == MPI_UNSIGNED_LONG) {
214     APPLY_FUNC(a, b, length, unsigned long, SUM_OP);
215   } else if(*datatype == MPI_FLOAT) {
216     APPLY_FUNC(a, b, length, float, SUM_OP);
217   } else if(*datatype == MPI_DOUBLE) {
218     APPLY_FUNC(a, b, length, double, SUM_OP);
219   } else if(*datatype == MPI_LONG_DOUBLE) {
220     APPLY_FUNC(a, b, length, long double, SUM_OP);
221   } else if(*datatype == MPI_C_FLOAT_COMPLEX) {
222     APPLY_FUNC(a, b, length, float _Complex, SUM_OP);
223   } else if(*datatype == MPI_C_DOUBLE_COMPLEX) {
224     APPLY_FUNC(a, b, length, double _Complex, SUM_OP);
225   } else if(*datatype == MPI_C_LONG_DOUBLE_COMPLEX) {
226     APPLY_FUNC(a, b, length, long double _Complex, SUM_OP);
227   }
228 }
229  
230 static void prod_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
231   if(*datatype == MPI_SHORT) {
232     APPLY_FUNC(a, b, length, short, PROD_OP);
233   } else if(*datatype == MPI_INT) {
234     APPLY_FUNC(a, b, length, int, PROD_OP);
235   } else if(*datatype == MPI_LONG) {
236     APPLY_FUNC(a, b, length, long, PROD_OP);
237   } else if(*datatype == MPI_UNSIGNED_SHORT) {
238     APPLY_FUNC(a, b, length, unsigned short, PROD_OP);
239   } else if(*datatype == MPI_UNSIGNED) {
240     APPLY_FUNC(a, b, length, unsigned int, PROD_OP);
241   } else if(*datatype == MPI_UNSIGNED_LONG) {
242     APPLY_FUNC(a, b, length, unsigned long, PROD_OP);
243   } else if(*datatype == MPI_FLOAT) {
244     APPLY_FUNC(a, b, length, float, PROD_OP);
245   } else if(*datatype == MPI_DOUBLE) {
246     APPLY_FUNC(a, b, length, double, PROD_OP);
247   } else if(*datatype == MPI_LONG_DOUBLE) {
248     APPLY_FUNC(a, b, length, long double, PROD_OP);
249   } else if(*datatype == MPI_C_FLOAT_COMPLEX) {
250     APPLY_FUNC(a, b, length, float _Complex, PROD_OP);
251   } else if(*datatype == MPI_C_DOUBLE_COMPLEX) {
252      APPLY_FUNC(a, b, length, double _Complex, PROD_OP);
253   } else if(*datatype == MPI_C_LONG_DOUBLE_COMPLEX) {
254     APPLY_FUNC(a, b, length, long double _Complex, PROD_OP);
255   }
256 }
257  
258 static void land_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
259   if(*datatype == MPI_SHORT) {
260     APPLY_FUNC(a, b, length, short, LAND_OP);
261   } else if(*datatype == MPI_INT) {
262     APPLY_FUNC(a, b, length, int, LAND_OP);
263   } else if(*datatype == MPI_LONG) {
264     APPLY_FUNC(a, b, length, long, LAND_OP);
265   } else if(*datatype == MPI_UNSIGNED_SHORT) {
266     APPLY_FUNC(a, b, length, unsigned short, LAND_OP);
267   } else if(*datatype == MPI_UNSIGNED) {
268     APPLY_FUNC(a, b, length, unsigned int, LAND_OP);
269   } else if(*datatype == MPI_UNSIGNED_LONG) {
270     APPLY_FUNC(a, b, length, unsigned long, LAND_OP);
271   } else if(*datatype == MPI_C_BOOL) {
272     APPLY_FUNC(a, b, length, _Bool, LAND_OP);
273   }
274 }
275  
276 static void lor_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
277   if(*datatype == MPI_SHORT) {
278     APPLY_FUNC(a, b, length, short, LOR_OP);
279   } else if(*datatype == MPI_INT) {
280     APPLY_FUNC(a, b, length, int, LOR_OP);
281   } else if(*datatype == MPI_LONG) {
282     APPLY_FUNC(a, b, length, long, LOR_OP);
283   } else if(*datatype == MPI_UNSIGNED_SHORT) {
284     APPLY_FUNC(a, b, length, unsigned short, LOR_OP);
285   } else if(*datatype == MPI_UNSIGNED) {
286     APPLY_FUNC(a, b, length, unsigned int, LOR_OP);
287   } else if(*datatype == MPI_UNSIGNED_LONG) {
288     APPLY_FUNC(a, b, length, unsigned long, LOR_OP);
289   } else if(*datatype == MPI_C_BOOL) {
290     APPLY_FUNC(a, b, length, _Bool, LOR_OP);
291   }
292 }
293  
294 static void lxor_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
295   if(*datatype == MPI_SHORT) {
296     APPLY_FUNC(a, b, length, short, LXOR_OP);
297   } else if(*datatype == MPI_INT) {
298     APPLY_FUNC(a, b, length, int, LXOR_OP);
299   } else if(*datatype == MPI_LONG) {
300     APPLY_FUNC(a, b, length, long, LXOR_OP);
301   } else if(*datatype == MPI_UNSIGNED_SHORT) {
302     APPLY_FUNC(a, b, length, unsigned short, LXOR_OP);
303   } else if(*datatype == MPI_UNSIGNED) {
304     APPLY_FUNC(a, b, length, unsigned int, LXOR_OP);
305   } else if(*datatype == MPI_UNSIGNED_LONG) {
306     APPLY_FUNC(a, b, length, unsigned long, LXOR_OP);
307   } else if(*datatype == MPI_C_BOOL) {
308     APPLY_FUNC(a, b, length, _Bool, LXOR_OP);
309   }
310 }
311  
312 static void band_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
313   if(*datatype == MPI_SHORT) {
314     APPLY_FUNC(a, b, length, short, BAND_OP);
315   } else if(*datatype == MPI_INT) {
316     APPLY_FUNC(a, b, length, int, BAND_OP);
317   } else if(*datatype == MPI_LONG) {
318     APPLY_FUNC(a, b, length, long, BAND_OP);
319   } else if(*datatype == MPI_UNSIGNED_SHORT) {
320     APPLY_FUNC(a, b, length, unsigned short, BAND_OP);
321   } else if(*datatype == MPI_UNSIGNED) {
322     APPLY_FUNC(a, b, length, unsigned int, BAND_OP);
323   } else if(*datatype == MPI_UNSIGNED_LONG) {
324     APPLY_FUNC(a, b, length, unsigned long, BAND_OP);
325   } else if(*datatype == MPI_BYTE) {
326     APPLY_FUNC(a, b, length, uint8_t, BAND_OP);
327   }
328 }
329  
330 static void bor_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
331   if(*datatype == MPI_SHORT) {
332     APPLY_FUNC(a, b, length, short, BOR_OP);
333   } else if(*datatype == MPI_INT) {
334     APPLY_FUNC(a, b, length, int, BOR_OP);
335   } else if(*datatype == MPI_LONG) {
336     APPLY_FUNC(a, b, length, long, BOR_OP);
337   } else if(*datatype == MPI_UNSIGNED_SHORT) {
338     APPLY_FUNC(a, b, length, unsigned short, BOR_OP);
339   } else if(*datatype == MPI_UNSIGNED) {
340     APPLY_FUNC(a, b, length, unsigned int, BOR_OP);
341   } else if(*datatype == MPI_UNSIGNED_LONG) {
342     APPLY_FUNC(a, b, length, unsigned long, BOR_OP);
343   } else if(*datatype == MPI_BYTE) {
344     APPLY_FUNC(a, b, length, uint8_t, BOR_OP);
345   }
346 }
347  
348 static void bxor_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
349   if(*datatype == MPI_SHORT) {
350     APPLY_FUNC(a, b, length, short, BXOR_OP);
351   } else if(*datatype == MPI_INT) {
352     APPLY_FUNC(a, b, length, int, BXOR_OP);
353   } else if(*datatype == MPI_LONG) {
354     APPLY_FUNC(a, b, length, long, BXOR_OP);
355   } else if(*datatype == MPI_UNSIGNED_SHORT) {
356     APPLY_FUNC(a, b, length, unsigned short, BXOR_OP);
357   } else if(*datatype == MPI_UNSIGNED) {
358     APPLY_FUNC(a, b, length, unsigned int, BXOR_OP);
359   } else if(*datatype == MPI_UNSIGNED_LONG) {
360     APPLY_FUNC(a, b, length, unsigned long, BXOR_OP);
361   } else if(*datatype == MPI_BYTE) {
362     APPLY_FUNC(a, b, length, uint8_t, BXOR_OP);
363   }
364 }
365
366 static void minloc_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
367   if(*datatype == MPI_FLOAT_INT) {
368     APPLY_FUNC(a, b, length, float_int, MINLOC_OP);
369   } else if(*datatype == MPI_LONG_INT) {
370     APPLY_FUNC(a, b, length, long_int, MINLOC_OP);
371   } else if(*datatype == MPI_DOUBLE_INT) {
372     APPLY_FUNC(a, b, length, double_int, MINLOC_OP);
373   } else if(*datatype == MPI_SHORT_INT) {
374     APPLY_FUNC(a, b, length, short_int, MINLOC_OP);
375   } else if(*datatype == MPI_2INT) {
376     APPLY_FUNC(a, b, length, int_int, MINLOC_OP);
377   } else if(*datatype == MPI_LONG_DOUBLE_INT) {
378     APPLY_FUNC(a, b, length, long_double_int, MINLOC_OP);
379   }
380 }
381
382 static void maxloc_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
383   if(*datatype == MPI_FLOAT_INT) {
384     APPLY_FUNC(a, b, length, float_int, MAXLOC_OP);
385   } else if(*datatype == MPI_LONG_INT) {
386     APPLY_FUNC(a, b, length, long_int, MAXLOC_OP);
387   } else if(*datatype == MPI_DOUBLE_INT) {
388     APPLY_FUNC(a, b, length, double_int, MAXLOC_OP);
389   } else if(*datatype == MPI_SHORT_INT) {
390     APPLY_FUNC(a, b, length, short_int, MAXLOC_OP);
391   } else if(*datatype == MPI_2INT) {
392     APPLY_FUNC(a, b, length, int_int, MAXLOC_OP);
393   } else if(*datatype == MPI_LONG_DOUBLE_INT) {
394     APPLY_FUNC(a, b, length, long_double_int, MAXLOC_OP);
395   }
396 }
397
398
399 #define CREATE_MPI_OP(name, func)                             \
400   static s_smpi_mpi_op_t mpi_##name = { &(func) /* func */ }; \
401   MPI_Op name = &mpi_##name;
402
403 CREATE_MPI_OP(MPI_MAX,     max_func);
404 CREATE_MPI_OP(MPI_MIN,     min_func);
405 CREATE_MPI_OP(MPI_SUM,     sum_func);
406 CREATE_MPI_OP(MPI_PROD,    prod_func);
407 CREATE_MPI_OP(MPI_LAND,    land_func);
408 CREATE_MPI_OP(MPI_LOR,     lor_func);
409 CREATE_MPI_OP(MPI_LXOR,    lxor_func);
410 CREATE_MPI_OP(MPI_BAND,    band_func);
411 CREATE_MPI_OP(MPI_BOR,     bor_func);
412 CREATE_MPI_OP(MPI_BXOR,    bxor_func);
413 CREATE_MPI_OP(MPI_MAXLOC,  maxloc_func);
414 CREATE_MPI_OP(MPI_MINLOC,  minloc_func);
415
416 MPI_Op smpi_op_new(MPI_User_function* function, int commute) {
417   MPI_Op op;
418
419   //FIXME: add commute param
420   op = xbt_new(s_smpi_mpi_op_t, 1);
421   op->func = function;
422   return op;
423 }
424
425 void smpi_op_destroy(MPI_Op op) {
426   xbt_free(op);
427 }
428
429 void smpi_op_apply(MPI_Op op, void* invec, void* inoutvec, int* len, MPI_Datatype* datatype) {
430   op->func(invec, inoutvec, len, datatype);
431 }