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.
38 typedef struct { float value; int index;} float_int;
39 typedef struct { long value; int index;} long_int ;
40 typedef struct { double value; int index;} double_int;
41 typedef struct { short value; int index;} short_int;
42 typedef struct { int value; int index;} int_int;
43 typedef struct { long double value; int index;} long_double_int;
45 // Predefined data types
46 CREATE_MPI_DATATYPE(MPI_CHAR, char);
47 CREATE_MPI_DATATYPE(MPI_SHORT, short);
48 CREATE_MPI_DATATYPE(MPI_INT, int);
49 CREATE_MPI_DATATYPE(MPI_LONG, long);
50 CREATE_MPI_DATATYPE(MPI_LONG_LONG, long long);
51 CREATE_MPI_DATATYPE(MPI_SIGNED_CHAR, signed char);
52 CREATE_MPI_DATATYPE(MPI_UNSIGNED_CHAR, unsigned char);
53 CREATE_MPI_DATATYPE(MPI_UNSIGNED_SHORT, unsigned short);
54 CREATE_MPI_DATATYPE(MPI_UNSIGNED, unsigned int);
55 CREATE_MPI_DATATYPE(MPI_UNSIGNED_LONG, unsigned long);
56 CREATE_MPI_DATATYPE(MPI_UNSIGNED_LONG_LONG, unsigned long long);
57 CREATE_MPI_DATATYPE(MPI_FLOAT, float);
58 CREATE_MPI_DATATYPE(MPI_DOUBLE, double);
59 CREATE_MPI_DATATYPE(MPI_LONG_DOUBLE, long double);
60 CREATE_MPI_DATATYPE(MPI_WCHAR, wchar_t);
61 CREATE_MPI_DATATYPE(MPI_C_BOOL, _Bool);
62 CREATE_MPI_DATATYPE(MPI_INT8_T, int8_t);
63 CREATE_MPI_DATATYPE(MPI_INT16_T, int16_t);
64 CREATE_MPI_DATATYPE(MPI_INT32_T, int32_t);
65 CREATE_MPI_DATATYPE(MPI_INT64_T, int64_t);
66 CREATE_MPI_DATATYPE(MPI_UINT8_T, uint8_t);
67 CREATE_MPI_DATATYPE(MPI_UINT16_T, uint16_t);
68 CREATE_MPI_DATATYPE(MPI_UINT32_T, uint32_t);
69 CREATE_MPI_DATATYPE(MPI_UINT64_T, uint64_t);
70 CREATE_MPI_DATATYPE(MPI_C_FLOAT_COMPLEX, float _Complex);
71 CREATE_MPI_DATATYPE(MPI_C_DOUBLE_COMPLEX, double _Complex);
72 CREATE_MPI_DATATYPE(MPI_C_LONG_DOUBLE_COMPLEX, long double _Complex);
73 CREATE_MPI_DATATYPE(MPI_AINT, MPI_Aint);
74 CREATE_MPI_DATATYPE(MPI_OFFSET, MPI_Offset);
76 CREATE_MPI_DATATYPE(MPI_FLOAT_INT, float_int);
77 CREATE_MPI_DATATYPE(MPI_LONG_INT, long_int);
78 CREATE_MPI_DATATYPE(MPI_DOUBLE_INT, double_int);
79 CREATE_MPI_DATATYPE(MPI_SHORT_INT, short_int);
80 CREATE_MPI_DATATYPE(MPI_2INT, int_int);
81 CREATE_MPI_DATATYPE(MPI_LONG_DOUBLE_INT, long_double_int);
84 size_t smpi_datatype_size(MPI_Datatype datatype) {
85 return datatype->size;
88 MPI_Aint smpi_datatype_lb(MPI_Datatype datatype) {
92 MPI_Aint smpi_datatype_ub(MPI_Datatype datatype) {
96 int smpi_datatype_extent(MPI_Datatype datatype, MPI_Aint* lb, MPI_Aint * extent) {
99 if((datatype->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED) {
100 retval = MPI_ERR_TYPE;
103 *extent = datatype->ub - datatype->lb;
104 retval = MPI_SUCCESS;
109 int smpi_datatype_copy(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype) {
112 /* First check if we really have something to do */
114 retval = sendcount == 0 ? MPI_SUCCESS : MPI_ERR_TRUNCATE;
115 } else if(sendtype == recvtype) {
116 /* If same datatypes used, just copy. */
117 count = sendcount < recvcount ? sendcount : recvcount;
118 memcpy(recvbuf, sendbuf, smpi_datatype_size(sendtype) * count);
119 retval = sendcount > recvcount ? MPI_ERR_TRUNCATE : MPI_SUCCESS;
122 * - If receive packed.
124 * to be treated once we have the MPI_Pack things ...
126 retval = MPI_SUCCESS;
131 typedef struct s_smpi_mpi_op {
132 MPI_User_function* func;
135 #define MAX_OP(a, b) (b) = (a) < (b) ? (b) : (a)
136 #define MIN_OP(a, b) (b) = (a) < (b) ? (a) : (b)
137 #define SUM_OP(a, b) (b) += (a)
138 #define PROD_OP(a, b) (b) *= (a)
139 #define LAND_OP(a, b) (b) = (a) && (b)
140 #define LOR_OP(a, b) (b) = (a) || (b)
141 #define LXOR_OP(a, b) (b) = (!(a) && (b)) || ((a) && !(b))
142 #define BAND_OP(a, b) (b) &= (a)
143 #define BOR_OP(a, b) (b) |= (a)
144 #define BXOR_OP(a, b) (b) ^= (a)
145 #define MAXLOC_OP(a, b) (b) = (a.value) < (b.value) ? (b) : (a)
146 #define MINLOC_OP(a, b) (b) = (a.value) < (b.value) ? (a) : (b)
147 //TODO : MINLOC & MAXLOC
149 #define APPLY_FUNC(a, b, length, type, func) \
152 type* x = (type*)(a); \
153 type* y = (type*)(b); \
154 for(i = 0; i < *(length); i++) { \
159 static void max_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
160 if(*datatype == MPI_SHORT) {
161 APPLY_FUNC(a, b, length, short, MAX_OP);
162 } else if(*datatype == MPI_INT) {
163 APPLY_FUNC(a, b, length, int, MAX_OP);
164 } else if(*datatype == MPI_LONG) {
165 APPLY_FUNC(a, b, length, long, MAX_OP);
166 } else if(*datatype == MPI_UNSIGNED_SHORT) {
167 APPLY_FUNC(a, b, length, unsigned short, MAX_OP);
168 } else if(*datatype == MPI_UNSIGNED) {
169 APPLY_FUNC(a, b, length, unsigned int, MAX_OP);
170 } else if(*datatype == MPI_UNSIGNED_LONG) {
171 APPLY_FUNC(a, b, length, unsigned long, MAX_OP);
172 } else if(*datatype == MPI_FLOAT) {
173 APPLY_FUNC(a, b, length, float, MAX_OP);
174 } else if(*datatype == MPI_DOUBLE) {
175 APPLY_FUNC(a, b, length, double, MAX_OP);
176 } else if(*datatype == MPI_LONG_DOUBLE) {
177 APPLY_FUNC(a, b, length, long double, MAX_OP);
181 static void min_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
182 if(*datatype == MPI_SHORT) {
183 APPLY_FUNC(a, b, length, short, MIN_OP);
184 } else if(*datatype == MPI_INT) {
185 APPLY_FUNC(a, b, length, int, MIN_OP);
186 } else if(*datatype == MPI_LONG) {
187 APPLY_FUNC(a, b, length, long, MIN_OP);
188 } else if(*datatype == MPI_UNSIGNED_SHORT) {
189 APPLY_FUNC(a, b, length, unsigned short, MIN_OP);
190 } else if(*datatype == MPI_UNSIGNED) {
191 APPLY_FUNC(a, b, length, unsigned int, MIN_OP);
192 } else if(*datatype == MPI_UNSIGNED_LONG) {
193 APPLY_FUNC(a, b, length, unsigned long, MIN_OP);
194 } else if(*datatype == MPI_FLOAT) {
195 APPLY_FUNC(a, b, length, float, MIN_OP);
196 } else if(*datatype == MPI_DOUBLE) {
197 APPLY_FUNC(a, b, length, double, MIN_OP);
198 } else if(*datatype == MPI_LONG_DOUBLE) {
199 APPLY_FUNC(a, b, length, long double, MIN_OP);
203 static void sum_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
204 if(*datatype == MPI_SHORT) {
205 APPLY_FUNC(a, b, length, short, SUM_OP);
206 } else if(*datatype == MPI_INT) {
207 APPLY_FUNC(a, b, length, int, SUM_OP);
208 } else if(*datatype == MPI_LONG) {
209 APPLY_FUNC(a, b, length, long, SUM_OP);
210 } else if(*datatype == MPI_UNSIGNED_SHORT) {
211 APPLY_FUNC(a, b, length, unsigned short, SUM_OP);
212 } else if(*datatype == MPI_UNSIGNED) {
213 APPLY_FUNC(a, b, length, unsigned int, SUM_OP);
214 } else if(*datatype == MPI_UNSIGNED_LONG) {
215 APPLY_FUNC(a, b, length, unsigned long, SUM_OP);
216 } else if(*datatype == MPI_FLOAT) {
217 APPLY_FUNC(a, b, length, float, SUM_OP);
218 } else if(*datatype == MPI_DOUBLE) {
219 APPLY_FUNC(a, b, length, double, SUM_OP);
220 } else if(*datatype == MPI_LONG_DOUBLE) {
221 APPLY_FUNC(a, b, length, long double, SUM_OP);
222 } else if(*datatype == MPI_C_FLOAT_COMPLEX) {
223 APPLY_FUNC(a, b, length, float _Complex, SUM_OP);
224 } else if(*datatype == MPI_C_DOUBLE_COMPLEX) {
225 APPLY_FUNC(a, b, length, double _Complex, SUM_OP);
226 } else if(*datatype == MPI_C_LONG_DOUBLE_COMPLEX) {
227 APPLY_FUNC(a, b, length, long double _Complex, SUM_OP);
231 static void prod_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
232 if(*datatype == MPI_SHORT) {
233 APPLY_FUNC(a, b, length, short, PROD_OP);
234 } else if(*datatype == MPI_INT) {
235 APPLY_FUNC(a, b, length, int, PROD_OP);
236 } else if(*datatype == MPI_LONG) {
237 APPLY_FUNC(a, b, length, long, PROD_OP);
238 } else if(*datatype == MPI_UNSIGNED_SHORT) {
239 APPLY_FUNC(a, b, length, unsigned short, PROD_OP);
240 } else if(*datatype == MPI_UNSIGNED) {
241 APPLY_FUNC(a, b, length, unsigned int, PROD_OP);
242 } else if(*datatype == MPI_UNSIGNED_LONG) {
243 APPLY_FUNC(a, b, length, unsigned long, PROD_OP);
244 } else if(*datatype == MPI_FLOAT) {
245 APPLY_FUNC(a, b, length, float, PROD_OP);
246 } else if(*datatype == MPI_DOUBLE) {
247 APPLY_FUNC(a, b, length, double, PROD_OP);
248 } else if(*datatype == MPI_LONG_DOUBLE) {
249 APPLY_FUNC(a, b, length, long double, PROD_OP);
250 } else if(*datatype == MPI_C_FLOAT_COMPLEX) {
251 APPLY_FUNC(a, b, length, float _Complex, PROD_OP);
252 } else if(*datatype == MPI_C_DOUBLE_COMPLEX) {
253 APPLY_FUNC(a, b, length, double _Complex, PROD_OP);
254 } else if(*datatype == MPI_C_LONG_DOUBLE_COMPLEX) {
255 APPLY_FUNC(a, b, length, long double _Complex, PROD_OP);
259 static void land_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
260 if(*datatype == MPI_SHORT) {
261 APPLY_FUNC(a, b, length, short, LAND_OP);
262 } else if(*datatype == MPI_INT) {
263 APPLY_FUNC(a, b, length, int, LAND_OP);
264 } else if(*datatype == MPI_LONG) {
265 APPLY_FUNC(a, b, length, long, LAND_OP);
266 } else if(*datatype == MPI_UNSIGNED_SHORT) {
267 APPLY_FUNC(a, b, length, unsigned short, LAND_OP);
268 } else if(*datatype == MPI_UNSIGNED) {
269 APPLY_FUNC(a, b, length, unsigned int, LAND_OP);
270 } else if(*datatype == MPI_UNSIGNED_LONG) {
271 APPLY_FUNC(a, b, length, unsigned long, LAND_OP);
272 } else if(*datatype == MPI_C_BOOL) {
273 APPLY_FUNC(a, b, length, _Bool, LAND_OP);
277 static void lor_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
278 if(*datatype == MPI_SHORT) {
279 APPLY_FUNC(a, b, length, short, LOR_OP);
280 } else if(*datatype == MPI_INT) {
281 APPLY_FUNC(a, b, length, int, LOR_OP);
282 } else if(*datatype == MPI_LONG) {
283 APPLY_FUNC(a, b, length, long, LOR_OP);
284 } else if(*datatype == MPI_UNSIGNED_SHORT) {
285 APPLY_FUNC(a, b, length, unsigned short, LOR_OP);
286 } else if(*datatype == MPI_UNSIGNED) {
287 APPLY_FUNC(a, b, length, unsigned int, LOR_OP);
288 } else if(*datatype == MPI_UNSIGNED_LONG) {
289 APPLY_FUNC(a, b, length, unsigned long, LOR_OP);
290 } else if(*datatype == MPI_C_BOOL) {
291 APPLY_FUNC(a, b, length, _Bool, LOR_OP);
295 static void lxor_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
296 if(*datatype == MPI_SHORT) {
297 APPLY_FUNC(a, b, length, short, LXOR_OP);
298 } else if(*datatype == MPI_INT) {
299 APPLY_FUNC(a, b, length, int, LXOR_OP);
300 } else if(*datatype == MPI_LONG) {
301 APPLY_FUNC(a, b, length, long, LXOR_OP);
302 } else if(*datatype == MPI_UNSIGNED_SHORT) {
303 APPLY_FUNC(a, b, length, unsigned short, LXOR_OP);
304 } else if(*datatype == MPI_UNSIGNED) {
305 APPLY_FUNC(a, b, length, unsigned int, LXOR_OP);
306 } else if(*datatype == MPI_UNSIGNED_LONG) {
307 APPLY_FUNC(a, b, length, unsigned long, LXOR_OP);
308 } else if(*datatype == MPI_C_BOOL) {
309 APPLY_FUNC(a, b, length, _Bool, LXOR_OP);
313 static void band_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
314 if(*datatype == MPI_SHORT) {
315 APPLY_FUNC(a, b, length, short, BAND_OP);
316 } else if(*datatype == MPI_INT) {
317 APPLY_FUNC(a, b, length, int, BAND_OP);
318 } else if(*datatype == MPI_LONG) {
319 APPLY_FUNC(a, b, length, long, BAND_OP);
320 } else if(*datatype == MPI_UNSIGNED_SHORT) {
321 APPLY_FUNC(a, b, length, unsigned short, BAND_OP);
322 } else if(*datatype == MPI_UNSIGNED) {
323 APPLY_FUNC(a, b, length, unsigned int, BAND_OP);
324 } else if(*datatype == MPI_UNSIGNED_LONG) {
325 APPLY_FUNC(a, b, length, unsigned long, BAND_OP);
326 } else if(*datatype == MPI_BYTE) {
327 APPLY_FUNC(a, b, length, uint8_t, BAND_OP);
331 static void bor_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
332 if(*datatype == MPI_SHORT) {
333 APPLY_FUNC(a, b, length, short, BOR_OP);
334 } else if(*datatype == MPI_INT) {
335 APPLY_FUNC(a, b, length, int, BOR_OP);
336 } else if(*datatype == MPI_LONG) {
337 APPLY_FUNC(a, b, length, long, BOR_OP);
338 } else if(*datatype == MPI_UNSIGNED_SHORT) {
339 APPLY_FUNC(a, b, length, unsigned short, BOR_OP);
340 } else if(*datatype == MPI_UNSIGNED) {
341 APPLY_FUNC(a, b, length, unsigned int, BOR_OP);
342 } else if(*datatype == MPI_UNSIGNED_LONG) {
343 APPLY_FUNC(a, b, length, unsigned long, BOR_OP);
344 } else if(*datatype == MPI_BYTE) {
345 APPLY_FUNC(a, b, length, uint8_t, BOR_OP);
349 static void bxor_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
350 if(*datatype == MPI_SHORT) {
351 APPLY_FUNC(a, b, length, short, BXOR_OP);
352 } else if(*datatype == MPI_INT) {
353 APPLY_FUNC(a, b, length, int, BXOR_OP);
354 } else if(*datatype == MPI_LONG) {
355 APPLY_FUNC(a, b, length, long, BXOR_OP);
356 } else if(*datatype == MPI_UNSIGNED_SHORT) {
357 APPLY_FUNC(a, b, length, unsigned short, BXOR_OP);
358 } else if(*datatype == MPI_UNSIGNED) {
359 APPLY_FUNC(a, b, length, unsigned int, BXOR_OP);
360 } else if(*datatype == MPI_UNSIGNED_LONG) {
361 APPLY_FUNC(a, b, length, unsigned long, BXOR_OP);
362 } else if(*datatype == MPI_BYTE) {
363 APPLY_FUNC(a, b, length, uint8_t, BXOR_OP);
367 static void minloc_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
368 if(*datatype == MPI_FLOAT_INT) {
369 APPLY_FUNC(a, b, length, float_int, MINLOC_OP);
370 } else if(*datatype == MPI_LONG_INT) {
371 APPLY_FUNC(a, b, length, long_int, MINLOC_OP);
372 } else if(*datatype == MPI_DOUBLE_INT) {
373 APPLY_FUNC(a, b, length, double_int, MINLOC_OP);
374 } else if(*datatype == MPI_SHORT_INT) {
375 APPLY_FUNC(a, b, length, short_int, MINLOC_OP);
376 } else if(*datatype == MPI_2INT) {
377 APPLY_FUNC(a, b, length, int_int, MINLOC_OP);
378 } else if(*datatype == MPI_LONG_DOUBLE_INT) {
379 APPLY_FUNC(a, b, length, long_double_int, MINLOC_OP);
383 static void maxloc_func(void* a, void* b, int* length, MPI_Datatype* datatype) {
384 if(*datatype == MPI_FLOAT_INT) {
385 APPLY_FUNC(a, b, length, float_int, MAXLOC_OP);
386 } else if(*datatype == MPI_LONG_INT) {
387 APPLY_FUNC(a, b, length, long_int, MAXLOC_OP);
388 } else if(*datatype == MPI_DOUBLE_INT) {
389 APPLY_FUNC(a, b, length, double_int, MAXLOC_OP);
390 } else if(*datatype == MPI_SHORT_INT) {
391 APPLY_FUNC(a, b, length, short_int, MAXLOC_OP);
392 } else if(*datatype == MPI_2INT) {
393 APPLY_FUNC(a, b, length, int_int, MAXLOC_OP);
394 } else if(*datatype == MPI_LONG_DOUBLE_INT) {
395 APPLY_FUNC(a, b, length, long_double_int, MAXLOC_OP);
400 #define CREATE_MPI_OP(name, func) \
401 static s_smpi_mpi_op_t mpi_##name = { &(func) /* func */ }; \
402 MPI_Op name = &mpi_##name;
404 CREATE_MPI_OP(MPI_MAX, max_func);
405 CREATE_MPI_OP(MPI_MIN, min_func);
406 CREATE_MPI_OP(MPI_SUM, sum_func);
407 CREATE_MPI_OP(MPI_PROD, prod_func);
408 CREATE_MPI_OP(MPI_LAND, land_func);
409 CREATE_MPI_OP(MPI_LOR, lor_func);
410 CREATE_MPI_OP(MPI_LXOR, lxor_func);
411 CREATE_MPI_OP(MPI_BAND, band_func);
412 CREATE_MPI_OP(MPI_BOR, bor_func);
413 CREATE_MPI_OP(MPI_BXOR, bxor_func);
414 CREATE_MPI_OP(MPI_MAXLOC, maxloc_func);
415 CREATE_MPI_OP(MPI_MINLOC, minloc_func);
417 MPI_Op smpi_op_new(MPI_User_function* function, int commute) {
420 //FIXME: add commute param
421 op = xbt_new(s_smpi_mpi_op_t, 1);
426 void smpi_op_destroy(MPI_Op op) {
430 void smpi_op_apply(MPI_Op op, void* invec, void* inoutvec, int* len, MPI_Datatype* datatype) {
431 op->func(invec, inoutvec, len, datatype);