00001
00002
00003
00004
00005
00006
00007
00008 #include "adio.h"
00009 #include "adio_extern.h"
00010
00011 static int MPIOI_Type_block(int *array_of_gsizes, int dim, int ndims, int nprocs,
00012 int rank, int darg, int order, MPI_Aint orig_extent,
00013 MPI_Datatype type_old, MPI_Datatype *type_new,
00014 MPI_Aint *st_offset);
00015 static int MPIOI_Type_cyclic(int *array_of_gsizes, int dim, int ndims, int nprocs,
00016 int rank, int darg, int order, MPI_Aint orig_extent,
00017 MPI_Datatype type_old, MPI_Datatype *type_new,
00018 MPI_Aint *st_offset);
00019
00020
00021 int ADIO_Type_create_darray(int size, int rank, int ndims,
00022 int *array_of_gsizes, int *array_of_distribs,
00023 int *array_of_dargs, int *array_of_psizes,
00024 int order, MPI_Datatype oldtype,
00025 MPI_Datatype *newtype)
00026 {
00027 MPI_Datatype type_old, type_new=MPI_DATATYPE_NULL, types[3];
00028 int procs, tmp_rank, i, tmp_size, blklens[3], *coords;
00029 MPI_Aint *st_offsets, orig_extent, disps[3];
00030
00031 MPI_Type_extent(oldtype, &orig_extent);
00032
00033
00034
00035 coords = (int *) ADIOI_Malloc(ndims*sizeof(int));
00036 procs = size;
00037 tmp_rank = rank;
00038 for (i=0; i<ndims; i++) {
00039 procs = procs/array_of_psizes[i];
00040 coords[i] = tmp_rank/procs;
00041 tmp_rank = tmp_rank % procs;
00042 }
00043
00044 st_offsets = (MPI_Aint *) ADIOI_Malloc(ndims*sizeof(MPI_Aint));
00045 type_old = oldtype;
00046
00047 if (order == MPI_ORDER_FORTRAN) {
00048
00049 for (i=0; i<ndims; i++) {
00050 switch(array_of_distribs[i]) {
00051 case MPI_DISTRIBUTE_BLOCK:
00052 MPIOI_Type_block(array_of_gsizes, i, ndims,
00053 array_of_psizes[i],
00054 coords[i], array_of_dargs[i],
00055 order, orig_extent,
00056 type_old, &type_new,
00057 st_offsets+i);
00058 break;
00059 case MPI_DISTRIBUTE_CYCLIC:
00060 MPIOI_Type_cyclic(array_of_gsizes, i, ndims,
00061 array_of_psizes[i], coords[i],
00062 array_of_dargs[i], order,
00063 orig_extent, type_old,
00064 &type_new, st_offsets+i);
00065 break;
00066 case MPI_DISTRIBUTE_NONE:
00067
00068 MPIOI_Type_block(array_of_gsizes, i, ndims, 1, 0,
00069 MPI_DISTRIBUTE_DFLT_DARG, order,
00070 orig_extent,
00071 type_old, &type_new,
00072 st_offsets+i);
00073 break;
00074 }
00075 if (i) MPI_Type_free(&type_old);
00076 type_old = type_new;
00077 }
00078
00079
00080 disps[1] = st_offsets[0];
00081 tmp_size = 1;
00082 for (i=1; i<ndims; i++) {
00083 tmp_size *= array_of_gsizes[i-1];
00084 disps[1] += (MPI_Aint)tmp_size*st_offsets[i];
00085 }
00086
00087 }
00088
00089 else {
00090
00091 for (i=ndims-1; i>=0; i--) {
00092 switch(array_of_distribs[i]) {
00093 case MPI_DISTRIBUTE_BLOCK:
00094 MPIOI_Type_block(array_of_gsizes, i, ndims, array_of_psizes[i],
00095 coords[i], array_of_dargs[i], order,
00096 orig_extent, type_old, &type_new,
00097 st_offsets+i);
00098 break;
00099 case MPI_DISTRIBUTE_CYCLIC:
00100 MPIOI_Type_cyclic(array_of_gsizes, i, ndims,
00101 array_of_psizes[i], coords[i],
00102 array_of_dargs[i], order,
00103 orig_extent, type_old, &type_new,
00104 st_offsets+i);
00105 break;
00106 case MPI_DISTRIBUTE_NONE:
00107
00108 MPIOI_Type_block(array_of_gsizes, i, ndims, array_of_psizes[i],
00109 coords[i], MPI_DISTRIBUTE_DFLT_DARG, order, orig_extent,
00110 type_old, &type_new, st_offsets+i);
00111 break;
00112 }
00113 if (i != ndims-1) MPI_Type_free(&type_old);
00114 type_old = type_new;
00115 }
00116
00117
00118 disps[1] = st_offsets[ndims-1];
00119 tmp_size = 1;
00120 for (i=ndims-2; i>=0; i--) {
00121 tmp_size *= array_of_gsizes[i+1];
00122 disps[1] += (MPI_Aint)tmp_size*st_offsets[i];
00123 }
00124 }
00125
00126 disps[1] *= orig_extent;
00127
00128 disps[2] = orig_extent;
00129 for (i=0; i<ndims; i++) disps[2] *= (MPI_Aint)array_of_gsizes[i];
00130
00131 disps[0] = 0;
00132 blklens[0] = blklens[1] = blklens[2] = 1;
00133 types[0] = MPI_LB;
00134 types[1] = type_new;
00135 types[2] = MPI_UB;
00136
00137 MPI_Type_struct(3, blklens, disps, types, newtype);
00138
00139 MPI_Type_free(&type_new);
00140 ADIOI_Free(st_offsets);
00141 ADIOI_Free(coords);
00142 return MPI_SUCCESS;
00143 }
00144
00145
00146
00147
00148
00149 static int MPIOI_Type_block(int *array_of_gsizes, int dim, int ndims, int nprocs,
00150 int rank, int darg, int order, MPI_Aint orig_extent,
00151 MPI_Datatype type_old, MPI_Datatype *type_new,
00152 MPI_Aint *st_offset)
00153 {
00154
00155
00156 int blksize, global_size, mysize, i, j;
00157 MPI_Aint stride;
00158
00159 global_size = array_of_gsizes[dim];
00160
00161 if (darg == MPI_DISTRIBUTE_DFLT_DARG)
00162 blksize = (global_size + nprocs - 1)/nprocs;
00163 else {
00164 blksize = darg;
00165
00166
00167 if (blksize <= 0) {
00168 return MPI_ERR_ARG;
00169 }
00170
00171 if (blksize * nprocs < global_size) {
00172 return MPI_ERR_ARG;
00173 }
00174
00175 }
00176
00177 j = global_size - blksize*rank;
00178 mysize = ADIOI_MIN(blksize, j);
00179 if (mysize < 0) mysize = 0;
00180
00181 stride = orig_extent;
00182 if (order == MPI_ORDER_FORTRAN) {
00183 if (dim == 0)
00184 MPI_Type_contiguous(mysize, type_old, type_new);
00185 else {
00186 for (i=0; i<dim; i++) stride *= (MPI_Aint)array_of_gsizes[i];
00187 MPI_Type_hvector(mysize, 1, stride, type_old, type_new);
00188 }
00189 }
00190 else {
00191 if (dim == ndims-1)
00192 MPI_Type_contiguous(mysize, type_old, type_new);
00193 else {
00194 for (i=ndims-1; i>dim; i--) stride *= (MPI_Aint)array_of_gsizes[i];
00195 MPI_Type_hvector(mysize, 1, stride, type_old, type_new);
00196 }
00197
00198 }
00199
00200 *st_offset = (MPI_Aint)blksize * (MPI_Aint)rank;
00201
00202 if (mysize == 0) *st_offset = 0;
00203
00204 return MPI_SUCCESS;
00205 }
00206
00207
00208
00209
00210
00211 static int MPIOI_Type_cyclic(int *array_of_gsizes, int dim, int ndims, int nprocs,
00212 int rank, int darg, int order, MPI_Aint orig_extent,
00213 MPI_Datatype type_old, MPI_Datatype *type_new,
00214 MPI_Aint *st_offset)
00215 {
00216
00217
00218 int blksize, i, blklens[3], st_index, end_index, local_size, rem, count;
00219 MPI_Aint stride, disps[3];
00220 MPI_Datatype type_tmp, types[3];
00221
00222 if (darg == MPI_DISTRIBUTE_DFLT_DARG) blksize = 1;
00223 else blksize = darg;
00224
00225
00226 if (blksize <= 0) {
00227 return MPI_ERR_ARG;
00228 }
00229
00230
00231 st_index = rank*blksize;
00232 end_index = array_of_gsizes[dim] - 1;
00233
00234 if (end_index < st_index) local_size = 0;
00235 else {
00236 local_size = ((end_index - st_index + 1)/(nprocs*blksize))*blksize;
00237 rem = (end_index - st_index + 1) % (nprocs*blksize);
00238 local_size += ADIOI_MIN(rem, blksize);
00239 }
00240
00241 count = local_size/blksize;
00242 rem = local_size % blksize;
00243
00244 stride = (MPI_Aint)nprocs*(MPI_Aint)blksize*orig_extent;
00245 if (order == MPI_ORDER_FORTRAN)
00246 for (i=0; i<dim; i++) stride *= (MPI_Aint)array_of_gsizes[i];
00247 else for (i=ndims-1; i>dim; i--) stride *= (MPI_Aint)array_of_gsizes[i];
00248
00249 MPI_Type_hvector(count, blksize, stride, type_old, type_new);
00250
00251 if (rem) {
00252
00253
00254
00255 types[0] = *type_new;
00256 types[1] = type_old;
00257 disps[0] = 0;
00258 disps[1] = (MPI_Aint)count*stride;
00259 blklens[0] = 1;
00260 blklens[1] = rem;
00261
00262 MPI_Type_struct(2, blklens, disps, types, &type_tmp);
00263
00264 MPI_Type_free(type_new);
00265 *type_new = type_tmp;
00266 }
00267
00268
00269
00270 if ( ((order == MPI_ORDER_FORTRAN) && (dim == 0)) ||
00271 ((order == MPI_ORDER_C) && (dim == ndims-1)) ) {
00272 types[0] = MPI_LB;
00273 disps[0] = 0;
00274 types[1] = *type_new;
00275 disps[1] = (MPI_Aint)rank * (MPI_Aint)blksize * orig_extent;
00276 types[2] = MPI_UB;
00277 disps[2] = orig_extent * (MPI_Aint)array_of_gsizes[dim];
00278 blklens[0] = blklens[1] = blklens[2] = 1;
00279 MPI_Type_struct(3, blklens, disps, types, &type_tmp);
00280 MPI_Type_free(type_new);
00281 *type_new = type_tmp;
00282
00283 *st_offset = 0;
00284
00285 }
00286 else {
00287 *st_offset = (MPI_Aint)rank * (MPI_Aint)blksize;
00288
00289
00290 }
00291
00292 if (local_size == 0) *st_offset = 0;
00293
00294 return MPI_SUCCESS;
00295 }