1 /* smpi_mpi_dt.c -- MPI primitives to handle datatypes */
2 /* FIXME: a very incomplete implementation */
4 /* Copyright (c) 2009, 2010. The SimGrid Team.
5 * All rights reserved. */
7 /* This program is free software; you can redistribute it and/or modify it
8 * under the terms of the license (GNU LGPL) which comes with this package. */
15 #include "smpi_mpi_dt_private.h"
17 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_mpi_dt, smpi,
18 "Logging specific to SMPI (datatype)");
20 typedef struct s_smpi_mpi_datatype {
25 } s_smpi_mpi_datatype_t;
27 #define CREATE_MPI_DATATYPE(name, type) \
28 static s_smpi_mpi_datatype_t mpi_##name = { \
29 sizeof(type), /* size */ \
31 sizeof(type), /* ub = lb + size */ \
32 DT_FLAG_BASIC /* flags */ \
34 MPI_Datatype name = &mpi_##name;
37 //The following are datatypes for the MPI functions MPI_MAXLOC and MPI_MINLOC.
63 // Predefined data types
64 CREATE_MPI_DATATYPE(MPI_CHAR, char);
65 CREATE_MPI_DATATYPE(MPI_SHORT, short);
66 CREATE_MPI_DATATYPE(MPI_INT, int);
67 CREATE_MPI_DATATYPE(MPI_LONG, long);
68 CREATE_MPI_DATATYPE(MPI_LONG_LONG, long long);
69 CREATE_MPI_DATATYPE(MPI_SIGNED_CHAR, signed char);
70 CREATE_MPI_DATATYPE(MPI_UNSIGNED_CHAR, unsigned char);
71 CREATE_MPI_DATATYPE(MPI_UNSIGNED_SHORT, unsigned short);
72 CREATE_MPI_DATATYPE(MPI_UNSIGNED, unsigned int);
73 CREATE_MPI_DATATYPE(MPI_UNSIGNED_LONG, unsigned long);
74 CREATE_MPI_DATATYPE(MPI_UNSIGNED_LONG_LONG, unsigned long long);
75 CREATE_MPI_DATATYPE(MPI_FLOAT, float);
76 CREATE_MPI_DATATYPE(MPI_DOUBLE, double);
77 CREATE_MPI_DATATYPE(MPI_LONG_DOUBLE, long double);
78 CREATE_MPI_DATATYPE(MPI_WCHAR, wchar_t);
79 CREATE_MPI_DATATYPE(MPI_C_BOOL, _Bool);
80 CREATE_MPI_DATATYPE(MPI_INT8_T, int8_t);
81 CREATE_MPI_DATATYPE(MPI_INT16_T, int16_t);
82 CREATE_MPI_DATATYPE(MPI_INT32_T, int32_t);
83 CREATE_MPI_DATATYPE(MPI_INT64_T, int64_t);
84 CREATE_MPI_DATATYPE(MPI_UINT8_T, uint8_t);
85 CREATE_MPI_DATATYPE(MPI_UINT16_T, uint16_t);
86 CREATE_MPI_DATATYPE(MPI_UINT32_T, uint32_t);
87 CREATE_MPI_DATATYPE(MPI_UINT64_T, uint64_t);
88 CREATE_MPI_DATATYPE(MPI_C_FLOAT_COMPLEX, float _Complex);
89 CREATE_MPI_DATATYPE(MPI_C_DOUBLE_COMPLEX, double _Complex);
90 CREATE_MPI_DATATYPE(MPI_C_LONG_DOUBLE_COMPLEX, long double _Complex);
91 CREATE_MPI_DATATYPE(MPI_AINT, MPI_Aint);
92 CREATE_MPI_DATATYPE(MPI_OFFSET, MPI_Offset);
94 CREATE_MPI_DATATYPE(MPI_FLOAT_INT, float_int);
95 CREATE_MPI_DATATYPE(MPI_LONG_INT, long_int);
96 CREATE_MPI_DATATYPE(MPI_DOUBLE_INT, double_int);
97 CREATE_MPI_DATATYPE(MPI_SHORT_INT, short_int);
98 CREATE_MPI_DATATYPE(MPI_2INT, int_int);
99 CREATE_MPI_DATATYPE(MPI_LONG_DOUBLE_INT, long_double_int);
102 CREATE_MPI_DATATYPE(MPI_PTR, void*);
105 size_t smpi_datatype_size(MPI_Datatype datatype)
107 return datatype->size;
110 MPI_Aint smpi_datatype_lb(MPI_Datatype datatype)
115 MPI_Aint smpi_datatype_ub(MPI_Datatype datatype)
120 int smpi_datatype_extent(MPI_Datatype datatype, MPI_Aint * lb,
125 if ((datatype->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED) {
126 retval = MPI_ERR_TYPE;
129 *extent = datatype->ub - datatype->lb;
130 retval = MPI_SUCCESS;
135 int smpi_datatype_copy(void *sendbuf, int sendcount, MPI_Datatype sendtype,
136 void *recvbuf, int recvcount, MPI_Datatype recvtype)
140 /* First check if we really have something to do */
141 if (recvcount == 0) {
142 retval = sendcount == 0 ? MPI_SUCCESS : MPI_ERR_TRUNCATE;
144 /* FIXME: treat packed cases */
145 sendcount *= smpi_datatype_size(sendtype);
146 recvcount *= smpi_datatype_size(recvtype);
147 count = sendcount < recvcount ? sendcount : recvcount;
148 memcpy(recvbuf, sendbuf, count);
149 retval = sendcount > recvcount ? MPI_ERR_TRUNCATE : MPI_SUCCESS;
154 typedef struct s_smpi_mpi_op {
155 MPI_User_function *func;
158 #define MAX_OP(a, b) (b) = (a) < (b) ? (b) : (a)
159 #define MIN_OP(a, b) (b) = (a) < (b) ? (a) : (b)
160 #define SUM_OP(a, b) (b) += (a)
161 #define PROD_OP(a, b) (b) *= (a)
162 #define LAND_OP(a, b) (b) = (a) && (b)
163 #define LOR_OP(a, b) (b) = (a) || (b)
164 #define LXOR_OP(a, b) (b) = (!(a) && (b)) || ((a) && !(b))
165 #define BAND_OP(a, b) (b) &= (a)
166 #define BOR_OP(a, b) (b) |= (a)
167 #define BXOR_OP(a, b) (b) ^= (a)
168 #define MAXLOC_OP(a, b) (b) = (a.value) < (b.value) ? (b) : (a)
169 #define MINLOC_OP(a, b) (b) = (a.value) < (b.value) ? (a) : (b)
170 //TODO : MINLOC & MAXLOC
172 #define APPLY_FUNC(a, b, length, type, func) \
175 type* x = (type*)(a); \
176 type* y = (type*)(b); \
177 for(i = 0; i < *(length); i++) { \
182 static void max_func(void *a, void *b, int *length,
183 MPI_Datatype * datatype)
185 if (*datatype == MPI_CHAR) {
186 APPLY_FUNC(a, b, length, char, MAX_OP);
187 } else if (*datatype == MPI_SHORT) {
188 APPLY_FUNC(a, b, length, short, MAX_OP);
189 } else if (*datatype == MPI_INT) {
190 APPLY_FUNC(a, b, length, int, MAX_OP);
191 } else if (*datatype == MPI_LONG) {
192 APPLY_FUNC(a, b, length, long, MAX_OP);
193 } else if (*datatype == MPI_UNSIGNED_SHORT) {
194 APPLY_FUNC(a, b, length, unsigned short, MAX_OP);
195 } else if (*datatype == MPI_UNSIGNED) {
196 APPLY_FUNC(a, b, length, unsigned int, MAX_OP);
197 } else if (*datatype == MPI_UNSIGNED_LONG) {
198 APPLY_FUNC(a, b, length, unsigned long, MAX_OP);
199 } else if (*datatype == MPI_FLOAT) {
200 APPLY_FUNC(a, b, length, float, MAX_OP);
201 } else if (*datatype == MPI_DOUBLE) {
202 APPLY_FUNC(a, b, length, double, MAX_OP);
203 } else if (*datatype == MPI_LONG_DOUBLE) {
204 APPLY_FUNC(a, b, length, long double, MAX_OP);
208 static void min_func(void *a, void *b, int *length,
209 MPI_Datatype * datatype)
211 if (*datatype == MPI_CHAR) {
212 APPLY_FUNC(a, b, length, char, MIN_OP);
213 } else if (*datatype == MPI_SHORT) {
214 APPLY_FUNC(a, b, length, short, MIN_OP);
215 } else if (*datatype == MPI_INT) {
216 APPLY_FUNC(a, b, length, int, MIN_OP);
217 } else if (*datatype == MPI_LONG) {
218 APPLY_FUNC(a, b, length, long, MIN_OP);
219 } else if (*datatype == MPI_UNSIGNED_SHORT) {
220 APPLY_FUNC(a, b, length, unsigned short, MIN_OP);
221 } else if (*datatype == MPI_UNSIGNED) {
222 APPLY_FUNC(a, b, length, unsigned int, MIN_OP);
223 } else if (*datatype == MPI_UNSIGNED_LONG) {
224 APPLY_FUNC(a, b, length, unsigned long, MIN_OP);
225 } else if (*datatype == MPI_FLOAT) {
226 APPLY_FUNC(a, b, length, float, MIN_OP);
227 } else if (*datatype == MPI_DOUBLE) {
228 APPLY_FUNC(a, b, length, double, MIN_OP);
229 } else if (*datatype == MPI_LONG_DOUBLE) {
230 APPLY_FUNC(a, b, length, long double, MIN_OP);
234 static void sum_func(void *a, void *b, int *length,
235 MPI_Datatype * datatype)
237 if (*datatype == MPI_CHAR) {
238 APPLY_FUNC(a, b, length, char, SUM_OP);
239 } else if (*datatype == MPI_SHORT) {
240 APPLY_FUNC(a, b, length, short, SUM_OP);
241 } else if (*datatype == MPI_INT) {
242 APPLY_FUNC(a, b, length, int, SUM_OP);
243 } else if (*datatype == MPI_LONG) {
244 APPLY_FUNC(a, b, length, long, SUM_OP);
245 } else if (*datatype == MPI_UNSIGNED_SHORT) {
246 APPLY_FUNC(a, b, length, unsigned short, SUM_OP);
247 } else if (*datatype == MPI_UNSIGNED) {
248 APPLY_FUNC(a, b, length, unsigned int, SUM_OP);
249 } else if (*datatype == MPI_UNSIGNED_LONG) {
250 APPLY_FUNC(a, b, length, unsigned long, SUM_OP);
251 } else if (*datatype == MPI_FLOAT) {
252 APPLY_FUNC(a, b, length, float, SUM_OP);
253 } else if (*datatype == MPI_DOUBLE) {
254 APPLY_FUNC(a, b, length, double, SUM_OP);
255 } else if (*datatype == MPI_LONG_DOUBLE) {
256 APPLY_FUNC(a, b, length, long double, SUM_OP);
257 } else if (*datatype == MPI_C_FLOAT_COMPLEX) {
258 APPLY_FUNC(a, b, length, float _Complex, SUM_OP);
259 } else if (*datatype == MPI_C_DOUBLE_COMPLEX) {
260 APPLY_FUNC(a, b, length, double _Complex, SUM_OP);
261 } else if (*datatype == MPI_C_LONG_DOUBLE_COMPLEX) {
262 APPLY_FUNC(a, b, length, long double _Complex, SUM_OP);
266 static void prod_func(void *a, void *b, int *length,
267 MPI_Datatype * datatype)
269 if (*datatype == MPI_CHAR) {
270 APPLY_FUNC(a, b, length, char, PROD_OP);
271 } else if (*datatype == MPI_SHORT) {
272 APPLY_FUNC(a, b, length, short, PROD_OP);
273 } else if (*datatype == MPI_INT) {
274 APPLY_FUNC(a, b, length, int, PROD_OP);
275 } else if (*datatype == MPI_LONG) {
276 APPLY_FUNC(a, b, length, long, PROD_OP);
277 } else if (*datatype == MPI_UNSIGNED_SHORT) {
278 APPLY_FUNC(a, b, length, unsigned short, PROD_OP);
279 } else if (*datatype == MPI_UNSIGNED) {
280 APPLY_FUNC(a, b, length, unsigned int, PROD_OP);
281 } else if (*datatype == MPI_UNSIGNED_LONG) {
282 APPLY_FUNC(a, b, length, unsigned long, PROD_OP);
283 } else if (*datatype == MPI_FLOAT) {
284 APPLY_FUNC(a, b, length, float, PROD_OP);
285 } else if (*datatype == MPI_DOUBLE) {
286 APPLY_FUNC(a, b, length, double, PROD_OP);
287 } else if (*datatype == MPI_LONG_DOUBLE) {
288 APPLY_FUNC(a, b, length, long double, PROD_OP);
289 } else if (*datatype == MPI_C_FLOAT_COMPLEX) {
290 APPLY_FUNC(a, b, length, float _Complex, PROD_OP);
291 } else if (*datatype == MPI_C_DOUBLE_COMPLEX) {
292 APPLY_FUNC(a, b, length, double _Complex, PROD_OP);
293 } else if (*datatype == MPI_C_LONG_DOUBLE_COMPLEX) {
294 APPLY_FUNC(a, b, length, long double _Complex, PROD_OP);
298 static void land_func(void *a, void *b, int *length,
299 MPI_Datatype * datatype)
301 if (*datatype == MPI_CHAR) {
302 APPLY_FUNC(a, b, length, char, LAND_OP);
303 } else if (*datatype == MPI_SHORT) {
304 APPLY_FUNC(a, b, length, short, LAND_OP);
305 } else if (*datatype == MPI_INT) {
306 APPLY_FUNC(a, b, length, int, LAND_OP);
307 } else if (*datatype == MPI_LONG) {
308 APPLY_FUNC(a, b, length, long, LAND_OP);
309 } else if (*datatype == MPI_UNSIGNED_SHORT) {
310 APPLY_FUNC(a, b, length, unsigned short, LAND_OP);
311 } else if (*datatype == MPI_UNSIGNED) {
312 APPLY_FUNC(a, b, length, unsigned int, LAND_OP);
313 } else if (*datatype == MPI_UNSIGNED_LONG) {
314 APPLY_FUNC(a, b, length, unsigned long, LAND_OP);
315 } else if (*datatype == MPI_C_BOOL) {
316 APPLY_FUNC(a, b, length, _Bool, LAND_OP);
320 static void lor_func(void *a, void *b, int *length,
321 MPI_Datatype * datatype)
323 if (*datatype == MPI_CHAR) {
324 APPLY_FUNC(a, b, length, char, LOR_OP);
325 } else if (*datatype == MPI_SHORT) {
326 APPLY_FUNC(a, b, length, short, LOR_OP);
327 } else if (*datatype == MPI_INT) {
328 APPLY_FUNC(a, b, length, int, LOR_OP);
329 } else if (*datatype == MPI_LONG) {
330 APPLY_FUNC(a, b, length, long, LOR_OP);
331 } else if (*datatype == MPI_UNSIGNED_SHORT) {
332 APPLY_FUNC(a, b, length, unsigned short, LOR_OP);
333 } else if (*datatype == MPI_UNSIGNED) {
334 APPLY_FUNC(a, b, length, unsigned int, LOR_OP);
335 } else if (*datatype == MPI_UNSIGNED_LONG) {
336 APPLY_FUNC(a, b, length, unsigned long, LOR_OP);
337 } else if (*datatype == MPI_C_BOOL) {
338 APPLY_FUNC(a, b, length, _Bool, LOR_OP);
342 static void lxor_func(void *a, void *b, int *length,
343 MPI_Datatype * datatype)
345 if (*datatype == MPI_CHAR) {
346 APPLY_FUNC(a, b, length, char, LXOR_OP);
347 } else if (*datatype == MPI_SHORT) {
348 APPLY_FUNC(a, b, length, short, LXOR_OP);
349 } else if (*datatype == MPI_INT) {
350 APPLY_FUNC(a, b, length, int, LXOR_OP);
351 } else if (*datatype == MPI_LONG) {
352 APPLY_FUNC(a, b, length, long, LXOR_OP);
353 } else if (*datatype == MPI_UNSIGNED_SHORT) {
354 APPLY_FUNC(a, b, length, unsigned short, LXOR_OP);
355 } else if (*datatype == MPI_UNSIGNED) {
356 APPLY_FUNC(a, b, length, unsigned int, LXOR_OP);
357 } else if (*datatype == MPI_UNSIGNED_LONG) {
358 APPLY_FUNC(a, b, length, unsigned long, LXOR_OP);
359 } else if (*datatype == MPI_C_BOOL) {
360 APPLY_FUNC(a, b, length, _Bool, LXOR_OP);
364 static void band_func(void *a, void *b, int *length,
365 MPI_Datatype * datatype)
367 if (*datatype == MPI_CHAR) {
368 APPLY_FUNC(a, b, length, char, BAND_OP);
370 if (*datatype == MPI_SHORT) {
371 APPLY_FUNC(a, b, length, short, BAND_OP);
372 } else if (*datatype == MPI_INT) {
373 APPLY_FUNC(a, b, length, int, BAND_OP);
374 } else if (*datatype == MPI_LONG) {
375 APPLY_FUNC(a, b, length, long, BAND_OP);
376 } else if (*datatype == MPI_UNSIGNED_SHORT) {
377 APPLY_FUNC(a, b, length, unsigned short, BAND_OP);
378 } else if (*datatype == MPI_UNSIGNED) {
379 APPLY_FUNC(a, b, length, unsigned int, BAND_OP);
380 } else if (*datatype == MPI_UNSIGNED_LONG) {
381 APPLY_FUNC(a, b, length, unsigned long, BAND_OP);
382 } else if (*datatype == MPI_BYTE) {
383 APPLY_FUNC(a, b, length, uint8_t, BAND_OP);
387 static void bor_func(void *a, void *b, int *length,
388 MPI_Datatype * datatype)
390 if (*datatype == MPI_CHAR) {
391 APPLY_FUNC(a, b, length, char, BOR_OP);
392 } else if (*datatype == MPI_SHORT) {
393 APPLY_FUNC(a, b, length, short, BOR_OP);
394 } else if (*datatype == MPI_INT) {
395 APPLY_FUNC(a, b, length, int, BOR_OP);
396 } else if (*datatype == MPI_LONG) {
397 APPLY_FUNC(a, b, length, long, BOR_OP);
398 } else if (*datatype == MPI_UNSIGNED_SHORT) {
399 APPLY_FUNC(a, b, length, unsigned short, BOR_OP);
400 } else if (*datatype == MPI_UNSIGNED) {
401 APPLY_FUNC(a, b, length, unsigned int, BOR_OP);
402 } else if (*datatype == MPI_UNSIGNED_LONG) {
403 APPLY_FUNC(a, b, length, unsigned long, BOR_OP);
404 } else if (*datatype == MPI_BYTE) {
405 APPLY_FUNC(a, b, length, uint8_t, BOR_OP);
409 static void bxor_func(void *a, void *b, int *length,
410 MPI_Datatype * datatype)
412 if (*datatype == MPI_CHAR) {
413 APPLY_FUNC(a, b, length, char, BXOR_OP);
414 } else if (*datatype == MPI_SHORT) {
415 APPLY_FUNC(a, b, length, short, BXOR_OP);
416 } else if (*datatype == MPI_INT) {
417 APPLY_FUNC(a, b, length, int, BXOR_OP);
418 } else if (*datatype == MPI_LONG) {
419 APPLY_FUNC(a, b, length, long, BXOR_OP);
420 } else if (*datatype == MPI_UNSIGNED_SHORT) {
421 APPLY_FUNC(a, b, length, unsigned short, BXOR_OP);
422 } else if (*datatype == MPI_UNSIGNED) {
423 APPLY_FUNC(a, b, length, unsigned int, BXOR_OP);
424 } else if (*datatype == MPI_UNSIGNED_LONG) {
425 APPLY_FUNC(a, b, length, unsigned long, BXOR_OP);
426 } else if (*datatype == MPI_BYTE) {
427 APPLY_FUNC(a, b, length, uint8_t, BXOR_OP);
431 static void minloc_func(void *a, void *b, int *length,
432 MPI_Datatype * datatype)
434 if (*datatype == MPI_FLOAT_INT) {
435 APPLY_FUNC(a, b, length, float_int, MINLOC_OP);
436 } else if (*datatype == MPI_LONG_INT) {
437 APPLY_FUNC(a, b, length, long_int, MINLOC_OP);
438 } else if (*datatype == MPI_DOUBLE_INT) {
439 APPLY_FUNC(a, b, length, double_int, MINLOC_OP);
440 } else if (*datatype == MPI_SHORT_INT) {
441 APPLY_FUNC(a, b, length, short_int, MINLOC_OP);
442 } else if (*datatype == MPI_2INT) {
443 APPLY_FUNC(a, b, length, int_int, MINLOC_OP);
444 } else if (*datatype == MPI_LONG_DOUBLE_INT) {
445 APPLY_FUNC(a, b, length, long_double_int, MINLOC_OP);
449 static void maxloc_func(void *a, void *b, int *length,
450 MPI_Datatype * datatype)
452 if (*datatype == MPI_FLOAT_INT) {
453 APPLY_FUNC(a, b, length, float_int, MAXLOC_OP);
454 } else if (*datatype == MPI_LONG_INT) {
455 APPLY_FUNC(a, b, length, long_int, MAXLOC_OP);
456 } else if (*datatype == MPI_DOUBLE_INT) {
457 APPLY_FUNC(a, b, length, double_int, MAXLOC_OP);
458 } else if (*datatype == MPI_SHORT_INT) {
459 APPLY_FUNC(a, b, length, short_int, MAXLOC_OP);
460 } else if (*datatype == MPI_2INT) {
461 APPLY_FUNC(a, b, length, int_int, MAXLOC_OP);
462 } else if (*datatype == MPI_LONG_DOUBLE_INT) {
463 APPLY_FUNC(a, b, length, long_double_int, MAXLOC_OP);
468 #define CREATE_MPI_OP(name, func) \
469 static s_smpi_mpi_op_t mpi_##name = { &(func) /* func */ }; \
470 MPI_Op name = &mpi_##name;
472 CREATE_MPI_OP(MPI_MAX, max_func);
473 CREATE_MPI_OP(MPI_MIN, min_func);
474 CREATE_MPI_OP(MPI_SUM, sum_func);
475 CREATE_MPI_OP(MPI_PROD, prod_func);
476 CREATE_MPI_OP(MPI_LAND, land_func);
477 CREATE_MPI_OP(MPI_LOR, lor_func);
478 CREATE_MPI_OP(MPI_LXOR, lxor_func);
479 CREATE_MPI_OP(MPI_BAND, band_func);
480 CREATE_MPI_OP(MPI_BOR, bor_func);
481 CREATE_MPI_OP(MPI_BXOR, bxor_func);
482 CREATE_MPI_OP(MPI_MAXLOC, maxloc_func);
483 CREATE_MPI_OP(MPI_MINLOC, minloc_func);
485 MPI_Op smpi_op_new(MPI_User_function * function, int commute)
489 //FIXME: add commute param
490 op = xbt_new(s_smpi_mpi_op_t, 1);
495 void smpi_op_destroy(MPI_Op op)
500 void smpi_op_apply(MPI_Op op, void *invec, void *inoutvec, int *len,
501 MPI_Datatype * datatype)
503 op->func(invec, inoutvec, len, datatype);