00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "adio.h"
00010 #include "adio_extern.h"
00011 #ifdef MPISGI
00012 #include "mpisgi2.h"
00013 #endif
00014
00015 void ADIOI_Optimize_flattened(ADIOI_Flatlist_node *flat_type);
00016
00017
00018 void ADIOI_Flatten_datatype(MPI_Datatype datatype)
00019 {
00020 int curr_index=0, is_contig;
00021 ADIOI_Flatlist_node *flat, *prev=0;
00022
00023
00024
00025
00026 ADIOI_Datatype_iscontig(datatype, &is_contig);
00027 if (is_contig) return;
00028
00029
00030 flat = ADIOI_Flatlist;
00031 while (flat) {
00032 if (flat->type == datatype) return;
00033 else {
00034 prev = flat;
00035 flat = flat->next;
00036 }
00037 }
00038
00039
00040 flat = prev;
00041 flat->next = (ADIOI_Flatlist_node *)ADIOI_Malloc(sizeof(ADIOI_Flatlist_node));
00042 flat = flat->next;
00043
00044 flat->type = datatype;
00045 flat->next = NULL;
00046 flat->blocklens = NULL;
00047 flat->indices = NULL;
00048
00049 flat->count = ADIOI_Count_contiguous_blocks(datatype, &curr_index);
00050
00051
00052 if (flat->count) {
00053 flat->blocklens = (int *) ADIOI_Malloc(flat->count * sizeof(int));
00054 flat->indices = (ADIO_Offset *) ADIOI_Malloc(flat->count * \
00055 sizeof(ADIO_Offset));
00056 }
00057
00058 curr_index = 0;
00059
00060 ADIOI_Flatten(datatype, flat, 0, &curr_index);
00061
00062 ADIOI_Optimize_flattened(flat);
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 }
00074
00075
00076 void ADIOI_Flatten(MPI_Datatype datatype, ADIOI_Flatlist_node *flat,
00077 ADIO_Offset st_offset, int *curr_index)
00078 {
00079 int i, j, k, m, n, num, basic_num, prev_index;
00080 int top_count, combiner, old_combiner, old_is_contig;
00081 int old_size, nints, nadds, ntypes, old_nints, old_nadds, old_ntypes;
00082 MPI_Aint old_extent;
00083 int *ints;
00084 MPI_Aint *adds;
00085 MPI_Datatype *types;
00086
00087 MPI_Type_get_envelope(datatype, &nints, &nadds, &ntypes, &combiner);
00088 ints = (int *) ADIOI_Malloc((nints+1)*sizeof(int));
00089 adds = (MPI_Aint *) ADIOI_Malloc((nadds+1)*sizeof(MPI_Aint));
00090 types = (MPI_Datatype *) ADIOI_Malloc((ntypes+1)*sizeof(MPI_Datatype));
00091 MPI_Type_get_contents(datatype, nints, nadds, ntypes, ints, adds, types);
00092
00093 switch (combiner) {
00094 #ifdef MPICH2
00095 case MPI_COMBINER_DUP:
00096 MPI_Type_get_envelope(types[0], &old_nints, &old_nadds,
00097 &old_ntypes, &old_combiner);
00098 ADIOI_Datatype_iscontig(types[0], &old_is_contig);
00099 if ((old_combiner != MPI_COMBINER_NAMED) && (!old_is_contig))
00100 ADIOI_Flatten(types[0], flat, st_offset, curr_index);
00101 break;
00102 #endif
00103 case MPI_COMBINER_CONTIGUOUS:
00104 top_count = ints[0];
00105 MPI_Type_get_envelope(types[0], &old_nints, &old_nadds,
00106 &old_ntypes, &old_combiner);
00107 ADIOI_Datatype_iscontig(types[0], &old_is_contig);
00108
00109 prev_index = *curr_index;
00110 if ((old_combiner != MPI_COMBINER_NAMED) && (!old_is_contig))
00111 ADIOI_Flatten(types[0], flat, st_offset, curr_index);
00112
00113 if (prev_index == *curr_index) {
00114
00115 j = *curr_index;
00116 flat->indices[j] = st_offset;
00117 MPI_Type_size(types[0], &old_size);
00118 flat->blocklens[j] = top_count * old_size;
00119 (*curr_index)++;
00120 }
00121 else {
00122
00123 j = *curr_index;
00124 num = *curr_index - prev_index;
00125
00126
00127 MPI_Type_extent(types[0], &old_extent);
00128 for (m=1; m<top_count; m++) {
00129 for (i=0; i<num; i++) {
00130 flat->indices[j] = flat->indices[j-num] + old_extent;
00131 flat->blocklens[j] = flat->blocklens[j-num];
00132 j++;
00133 }
00134 }
00135 *curr_index = j;
00136 }
00137 break;
00138
00139 case MPI_COMBINER_VECTOR:
00140 top_count = ints[0];
00141 MPI_Type_get_envelope(types[0], &old_nints, &old_nadds,
00142 &old_ntypes, &old_combiner);
00143 ADIOI_Datatype_iscontig(types[0], &old_is_contig);
00144
00145 prev_index = *curr_index;
00146 if ((old_combiner != MPI_COMBINER_NAMED) && (!old_is_contig))
00147 ADIOI_Flatten(types[0], flat, st_offset, curr_index);
00148
00149 if (prev_index == *curr_index) {
00150
00151 j = *curr_index;
00152 flat->indices[j] = st_offset;
00153 MPI_Type_size(types[0], &old_size);
00154 flat->blocklens[j] = ints[1] * old_size;
00155 for (i=j+1; i<j+top_count; i++) {
00156 flat->indices[i] = flat->indices[i-1] + ints[2]*old_size;
00157 flat->blocklens[i] = flat->blocklens[j];
00158 }
00159 *curr_index = i;
00160 }
00161 else {
00162
00163
00164 j = *curr_index;
00165 num = *curr_index - prev_index;
00166
00167
00168
00169 MPI_Type_extent(types[0], &old_extent);
00170 for (m=1; m<ints[1]; m++) {
00171 for (i=0; i<num; i++) {
00172 flat->indices[j] = flat->indices[j-num] + old_extent;
00173 flat->blocklens[j] = flat->blocklens[j-num];
00174 j++;
00175 }
00176 }
00177 *curr_index = j;
00178
00179
00180 num = *curr_index - prev_index;
00181 for (i=1; i<top_count; i++) {
00182 for (m=0; m<num; m++) {
00183 flat->indices[j] = flat->indices[j-num] + ints[2]
00184 *old_extent;
00185 flat->blocklens[j] = flat->blocklens[j-num];
00186 j++;
00187 }
00188 }
00189 *curr_index = j;
00190 }
00191 break;
00192
00193 case MPI_COMBINER_HVECTOR:
00194 top_count = ints[0];
00195 MPI_Type_get_envelope(types[0], &old_nints, &old_nadds,
00196 &old_ntypes, &old_combiner);
00197 ADIOI_Datatype_iscontig(types[0], &old_is_contig);
00198
00199 prev_index = *curr_index;
00200 if ((old_combiner != MPI_COMBINER_NAMED) && (!old_is_contig))
00201 ADIOI_Flatten(types[0], flat, st_offset, curr_index);
00202
00203 if (prev_index == *curr_index) {
00204
00205 j = *curr_index;
00206 flat->indices[j] = st_offset;
00207 MPI_Type_size(types[0], &old_size);
00208 flat->blocklens[j] = ints[1] * old_size;
00209 for (i=j+1; i<j+top_count; i++) {
00210 flat->indices[i] = flat->indices[i-1] + adds[0];
00211 flat->blocklens[i] = flat->blocklens[j];
00212 }
00213 *curr_index = i;
00214 }
00215 else {
00216
00217
00218 j = *curr_index;
00219 num = *curr_index - prev_index;
00220
00221
00222
00223 MPI_Type_extent(types[0], &old_extent);
00224 for (m=1; m<ints[1]; m++) {
00225 for (i=0; i<num; i++) {
00226 flat->indices[j] = flat->indices[j-num] + old_extent;
00227 flat->blocklens[j] = flat->blocklens[j-num];
00228 j++;
00229 }
00230 }
00231 *curr_index = j;
00232
00233
00234 num = *curr_index - prev_index;
00235 for (i=1; i<top_count; i++) {
00236 for (m=0; m<num; m++) {
00237 flat->indices[j] = flat->indices[j-num] + adds[0];
00238 flat->blocklens[j] = flat->blocklens[j-num];
00239 j++;
00240 }
00241 }
00242 *curr_index = j;
00243 }
00244 break;
00245
00246 case MPI_COMBINER_INDEXED:
00247 top_count = ints[0];
00248 MPI_Type_get_envelope(types[0], &old_nints, &old_nadds,
00249 &old_ntypes, &old_combiner);
00250 ADIOI_Datatype_iscontig(types[0], &old_is_contig);
00251 MPI_Type_extent(types[0], &old_extent);
00252
00253 prev_index = *curr_index;
00254 if ((old_combiner != MPI_COMBINER_NAMED) && (!old_is_contig))
00255 ADIOI_Flatten(types[0], flat,
00256 st_offset+ints[top_count+1]*old_extent, curr_index);
00257
00258 if (prev_index == *curr_index) {
00259
00260 j = *curr_index;
00261 for (i=j; i<j+top_count; i++) {
00262 flat->indices[i] = st_offset + ints[top_count+1+i-j]*old_extent;
00263 flat->blocklens[i] = (int) (ints[1+i-j]*old_extent);
00264 }
00265 *curr_index = i;
00266 }
00267 else {
00268
00269
00270 j = *curr_index;
00271 num = *curr_index - prev_index;
00272 basic_num = num;
00273
00274
00275
00276 for (m=1; m<ints[1]; m++) {
00277 for (i=0; i<num; i++) {
00278 flat->indices[j] = flat->indices[j-num] + old_extent;
00279 flat->blocklens[j] = flat->blocklens[j-num];
00280 j++;
00281 }
00282 }
00283 *curr_index = j;
00284
00285
00286 for (i=1; i<top_count; i++) {
00287 num = *curr_index - prev_index;
00288 prev_index = *curr_index;
00289 for (m=0; m<basic_num; m++) {
00290 flat->indices[j] = flat->indices[j-num] +
00291 (ints[top_count+1+i]-ints[top_count+i])*old_extent;
00292 flat->blocklens[j] = flat->blocklens[j-num];
00293 j++;
00294 }
00295 *curr_index = j;
00296 for (m=1; m<ints[1+i]; m++) {
00297 for (k=0; k<basic_num; k++) {
00298 flat->indices[j] = flat->indices[j-basic_num] + old_extent;
00299 flat->blocklens[j] = flat->blocklens[j-basic_num];
00300 j++;
00301 }
00302 }
00303 *curr_index = j;
00304 }
00305 }
00306 break;
00307
00308 case MPI_COMBINER_HINDEXED:
00309 top_count = ints[0];
00310 MPI_Type_get_envelope(types[0], &old_nints, &old_nadds,
00311 &old_ntypes, &old_combiner);
00312 ADIOI_Datatype_iscontig(types[0], &old_is_contig);
00313
00314 prev_index = *curr_index;
00315 if ((old_combiner != MPI_COMBINER_NAMED) && (!old_is_contig))
00316 ADIOI_Flatten(types[0], flat, st_offset+adds[0], curr_index);
00317
00318 if (prev_index == *curr_index) {
00319
00320 j = *curr_index;
00321 MPI_Type_size(types[0], &old_size);
00322 for (i=j; i<j+top_count; i++) {
00323 flat->indices[i] = st_offset + adds[i-j];
00324 flat->blocklens[i] = ints[1+i-j]*old_size;
00325 }
00326 *curr_index = i;
00327 }
00328 else {
00329
00330
00331 j = *curr_index;
00332 num = *curr_index - prev_index;
00333 basic_num = num;
00334
00335
00336
00337 MPI_Type_extent(types[0], &old_extent);
00338 for (m=1; m<ints[1]; m++) {
00339 for (i=0; i<num; i++) {
00340 flat->indices[j] = flat->indices[j-num] + old_extent;
00341 flat->blocklens[j] = flat->blocklens[j-num];
00342 j++;
00343 }
00344 }
00345 *curr_index = j;
00346
00347
00348 for (i=1; i<top_count; i++) {
00349 num = *curr_index - prev_index;
00350 prev_index = *curr_index;
00351 for (m=0; m<basic_num; m++) {
00352 flat->indices[j] = flat->indices[j-num] + adds[i] - adds[i-1];
00353 flat->blocklens[j] = flat->blocklens[j-num];
00354 j++;
00355 }
00356 *curr_index = j;
00357 for (m=1; m<ints[1+i]; m++) {
00358 for (k=0; k<basic_num; k++) {
00359 flat->indices[j] = flat->indices[j-basic_num] + old_extent;
00360 flat->blocklens[j] = flat->blocklens[j-basic_num];
00361 j++;
00362 }
00363 }
00364 *curr_index = j;
00365 }
00366 }
00367 break;
00368
00369 case MPI_COMBINER_STRUCT:
00370 top_count = ints[0];
00371 for (n=0; n<top_count; n++) {
00372 MPI_Type_get_envelope(types[n], &old_nints, &old_nadds,
00373 &old_ntypes, &old_combiner);
00374 ADIOI_Datatype_iscontig(types[n], &old_is_contig);
00375
00376 prev_index = *curr_index;
00377 if ((old_combiner != MPI_COMBINER_NAMED) && (!old_is_contig))
00378 ADIOI_Flatten(types[n], flat, st_offset+adds[n], curr_index);
00379
00380 if (prev_index == *curr_index) {
00381
00382 j = *curr_index;
00383 flat->indices[j] = st_offset + adds[n];
00384 MPI_Type_size(types[n], &old_size);
00385 flat->blocklens[j] = ints[1+n] * old_size;
00386 (*curr_index)++;
00387 }
00388 else {
00389
00390
00391 j = *curr_index;
00392 num = *curr_index - prev_index;
00393
00394
00395 MPI_Type_extent(types[n], &old_extent);
00396 for (m=1; m<ints[1+n]; m++) {
00397 for (i=0; i<num; i++) {
00398 flat->indices[j] = flat->indices[j-num] + old_extent;
00399 flat->blocklens[j] = flat->blocklens[j-num];
00400 j++;
00401 }
00402 }
00403 *curr_index = j;
00404 }
00405 }
00406 break;
00407
00408 default:
00409 FPRINTF(stderr, "Error: Unsupported datatype passed to ADIOI_Flatten\n");
00410 MPI_Abort(MPI_COMM_WORLD, 1);
00411 }
00412
00413 #ifndef MPISGI
00414
00415
00416 for (i=0; i<ntypes; i++) {
00417 MPI_Type_get_envelope(types[i], &old_nints, &old_nadds, &old_ntypes,
00418 &old_combiner);
00419 if (old_combiner != MPI_COMBINER_NAMED) MPI_Type_free(types+i);
00420 }
00421 #endif
00422
00423 ADIOI_Free(ints);
00424 ADIOI_Free(adds);
00425 ADIOI_Free(types);
00426 }
00427
00428
00429
00430
00431
00432
00433 int ADIOI_Count_contiguous_blocks(MPI_Datatype datatype, int *curr_index)
00434 {
00435 int count=0, i, n, num, basic_num, prev_index;
00436 int top_count, combiner, old_combiner, old_is_contig;
00437 int nints, nadds, ntypes, old_nints, old_nadds, old_ntypes;
00438 int *ints;
00439 MPI_Aint *adds;
00440 MPI_Datatype *types;
00441
00442 MPI_Type_get_envelope(datatype, &nints, &nadds, &ntypes, &combiner);
00443 ints = (int *) ADIOI_Malloc((nints+1)*sizeof(int));
00444 adds = (MPI_Aint *) ADIOI_Malloc((nadds+1)*sizeof(MPI_Aint));
00445 types = (MPI_Datatype *) ADIOI_Malloc((ntypes+1)*sizeof(MPI_Datatype));
00446 MPI_Type_get_contents(datatype, nints, nadds, ntypes, ints, adds, types);
00447
00448 switch (combiner) {
00449 #ifdef MPICH2
00450 case MPI_COMBINER_DUP:
00451 MPI_Type_get_envelope(types[0], &old_nints, &old_nadds,
00452 &old_ntypes, &old_combiner);
00453 ADIOI_Datatype_iscontig(types[0], &old_is_contig);
00454 if ((old_combiner != MPI_COMBINER_NAMED) && (!old_is_contig))
00455 count = ADIOI_Count_contiguous_blocks(types[0], curr_index);
00456 else count = 1;
00457 break;
00458 #endif
00459 case MPI_COMBINER_CONTIGUOUS:
00460 top_count = ints[0];
00461 MPI_Type_get_envelope(types[0], &old_nints, &old_nadds,
00462 &old_ntypes, &old_combiner);
00463 ADIOI_Datatype_iscontig(types[0], &old_is_contig);
00464
00465 prev_index = *curr_index;
00466 if ((old_combiner != MPI_COMBINER_NAMED) && (!old_is_contig))
00467 count = ADIOI_Count_contiguous_blocks(types[0], curr_index);
00468 else count = 1;
00469
00470 if (prev_index == *curr_index)
00471
00472 (*curr_index)++;
00473 else {
00474
00475 num = *curr_index - prev_index;
00476 count *= top_count;
00477 *curr_index += (top_count - 1)*num;
00478 }
00479 break;
00480
00481 case MPI_COMBINER_VECTOR:
00482 case MPI_COMBINER_HVECTOR:
00483 top_count = ints[0];
00484 MPI_Type_get_envelope(types[0], &old_nints, &old_nadds,
00485 &old_ntypes, &old_combiner);
00486 ADIOI_Datatype_iscontig(types[0], &old_is_contig);
00487
00488 prev_index = *curr_index;
00489 if ((old_combiner != MPI_COMBINER_NAMED) && (!old_is_contig))
00490 count = ADIOI_Count_contiguous_blocks(types[0], curr_index);
00491 else count = 1;
00492
00493 if (prev_index == *curr_index) {
00494
00495 count = top_count;
00496 *curr_index += count;
00497 }
00498 else {
00499
00500 num = *curr_index - prev_index;
00501
00502
00503
00504 count *= ints[1] * top_count;
00505
00506
00507 *curr_index += (ints[1] - 1)*num;
00508
00509
00510 num = *curr_index - prev_index;
00511 *curr_index += (top_count - 1)*num;
00512 }
00513 break;
00514
00515 case MPI_COMBINER_INDEXED:
00516 case MPI_COMBINER_HINDEXED:
00517 top_count = ints[0];
00518 MPI_Type_get_envelope(types[0], &old_nints, &old_nadds,
00519 &old_ntypes, &old_combiner);
00520 ADIOI_Datatype_iscontig(types[0], &old_is_contig);
00521
00522 prev_index = *curr_index;
00523 if ((old_combiner != MPI_COMBINER_NAMED) && (!old_is_contig))
00524 count = ADIOI_Count_contiguous_blocks(types[0], curr_index);
00525 else count = 1;
00526
00527 if (prev_index == *curr_index) {
00528
00529 count = top_count;
00530 *curr_index += count;
00531 }
00532 else {
00533
00534 basic_num = *curr_index - prev_index;
00535
00536
00537
00538 *curr_index += (ints[1]-1) * basic_num;
00539 count *= ints[1];
00540
00541
00542 for (i=1; i<top_count; i++) {
00543 count += ints[1+i] * basic_num;
00544 *curr_index += ints[1+i] * basic_num;
00545 }
00546 }
00547 break;
00548
00549 case MPI_COMBINER_STRUCT:
00550 top_count = ints[0];
00551 count = 0;
00552 for (n=0; n<top_count; n++) {
00553 MPI_Type_get_envelope(types[n], &old_nints, &old_nadds,
00554 &old_ntypes, &old_combiner);
00555 ADIOI_Datatype_iscontig(types[n], &old_is_contig);
00556
00557 prev_index = *curr_index;
00558 if ((old_combiner != MPI_COMBINER_NAMED) && (!old_is_contig))
00559 count += ADIOI_Count_contiguous_blocks(types[n], curr_index);
00560
00561 if (prev_index == *curr_index) {
00562
00563 count++;
00564 (*curr_index)++;
00565 }
00566 else {
00567
00568
00569
00570 num = *curr_index - prev_index;
00571 count += (ints[1+n]-1)*num;
00572 (*curr_index) += (ints[1+n]-1)*num;
00573 }
00574 }
00575 break;
00576 default:
00577 FPRINTF(stderr, "Error: Unsupported datatype passed to ADIOI_Count_contiguous_blocks\n");
00578 MPI_Abort(MPI_COMM_WORLD, 1);
00579 }
00580
00581 #ifndef MPISGI
00582
00583
00584 for (i=0; i<ntypes; i++) {
00585 MPI_Type_get_envelope(types[i], &old_nints, &old_nadds, &old_ntypes,
00586 &old_combiner);
00587 if (old_combiner != MPI_COMBINER_NAMED) MPI_Type_free(types+i);
00588 }
00589 #endif
00590
00591 ADIOI_Free(ints);
00592 ADIOI_Free(adds);
00593 ADIOI_Free(types);
00594 return count;
00595 }
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606 void ADIOI_Optimize_flattened(ADIOI_Flatlist_node *flat_type)
00607 {
00608 int i, j, opt_blocks;
00609 int *opt_blocklens;
00610 ADIO_Offset *opt_indices;
00611
00612 opt_blocks = 1;
00613
00614
00615 for (i=0; i < (flat_type->count - 1); i++) {
00616 if ((flat_type->indices[i] + flat_type->blocklens[i] !=
00617 flat_type->indices[i + 1]))
00618 opt_blocks++;
00619 }
00620
00621
00622 if (opt_blocks == flat_type->count) return;
00623
00624 opt_blocklens = (int *) ADIOI_Malloc(opt_blocks * sizeof(int));
00625 opt_indices = (ADIO_Offset *)ADIOI_Malloc(opt_blocks*sizeof(ADIO_Offset));
00626
00627
00628 opt_blocklens[0] = flat_type->blocklens[0];
00629 opt_indices[0] = flat_type->indices[0];
00630 j = 0;
00631 for (i=0; i < (flat_type->count - 1); i++) {
00632 if ((flat_type->indices[i] + flat_type->blocklens[i] ==
00633 flat_type->indices[i + 1]))
00634 opt_blocklens[j] += flat_type->blocklens[i + 1];
00635 else {
00636 j++;
00637 opt_indices[j] = flat_type->indices[i + 1];
00638 opt_blocklens[j] = flat_type->blocklens[i + 1];
00639 }
00640 }
00641 flat_type->count = opt_blocks;
00642 ADIOI_Free(flat_type->blocklens);
00643 ADIOI_Free(flat_type->indices);
00644 flat_type->blocklens = opt_blocklens;
00645 flat_type->indices = opt_indices;
00646 return;
00647 }
00648
00649
00650
00651 void ADIOI_Delete_flattened(MPI_Datatype datatype)
00652 {
00653 ADIOI_Flatlist_node *flat, *prev;
00654
00655 prev = flat = ADIOI_Flatlist;
00656 while (flat && (flat->type != datatype)) {
00657 prev = flat;
00658 flat = flat->next;
00659 }
00660 if (flat) {
00661 prev->next = flat->next;
00662 if (flat->blocklens) ADIOI_Free(flat->blocklens);
00663 if (flat->indices) ADIOI_Free(flat->indices);
00664 ADIOI_Free(flat);
00665 }
00666 }
00667