Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add new entry in Release_Notes.
[simgrid.git] / teshsuite / smpi / mpich3-test / datatype / large_type.c
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  *
4  *  (C) 2013 by Argonne National Laboratory.
5  *      See COPYRIGHT in top-level directory.
6  */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <mpi.h>
11
12 static MPI_Datatype make_largexfer_type_struct(MPI_Offset nbytes)
13 {
14     int typechunk_size = 1024 * 1024;   /* in bytes: TODO: figure out how big a
15                                          * chunk is really needed */
16     int chunk_count;
17     int remainder = 0;
18     MPI_Datatype memtype, chunktype;
19
20     /* need to cook up a new datatype to accommodate large datatypes */
21     /* first pass: chunks of 1 MiB plus an additional remainder.  Does require
22      * 8 byte MPI_Aint, which should have been checked for earlier */
23
24     chunk_count = nbytes / typechunk_size;
25     remainder = nbytes % typechunk_size;
26     MPI_Type_contiguous(typechunk_size, MPI_BYTE, &chunktype);
27     MPI_Type_commit(&chunktype);
28
29     /* a zero remainder means we can just count contigs */
30     if (remainder == 0) {
31         MPI_Type_contiguous(chunk_count, chunktype, &memtype);
32         MPI_Type_free(&chunktype);
33     }
34     else {
35         if (sizeof(MPI_Aint) <= sizeof(int)) {
36             return MPI_DATATYPE_NULL;
37         }
38         /* struct type: some number of chunks plus remaining bytes tacked
39          * on at end */
40         int lens[] = { chunk_count, remainder };
41         MPI_Aint disp[] = { 0, (MPI_Aint) typechunk_size * (MPI_Aint) chunk_count };
42         MPI_Datatype types[] = { chunktype, MPI_BYTE };
43
44         MPI_Type_struct(2, lens, disp, types, &memtype);
45         MPI_Type_free(&chunktype);
46     }
47     MPI_Type_commit(&memtype);
48     return memtype;
49 }
50
51 static MPI_Datatype make_largexfer_type_hindexed(MPI_Offset nbytes)
52 {
53     int i, count;
54     int chunk_size = 1024 * 1024;
55     int *blocklens;
56     MPI_Aint *disp;
57     MPI_Datatype memtype;
58
59     /* need to cook up a new datatype to accommodate large datatypes */
60     /* Does require 8 byte MPI_Aint, which should have been checked for earlier
61      */
62
63     if (sizeof(MPI_Aint) <= sizeof(int)) {
64         return MPI_DATATYPE_NULL;
65     }
66
67     /* ceiling division */
68     count = 1 + ((nbytes - 1) / chunk_size);
69
70     blocklens = calloc(count, sizeof(int));
71     disp = calloc(count, sizeof(MPI_Aint));
72
73
74     for (i = 0; i < (count - 1); i++) {
75         blocklens[i] = chunk_size;
76         disp[i] = (MPI_Aint) chunk_size *i;
77     }
78     blocklens[count - 1] = nbytes - ((MPI_Aint) chunk_size * i);
79     disp[count - 1] = (MPI_Aint) chunk_size *(count - 1);
80
81     MPI_Type_create_hindexed(count, blocklens, disp, MPI_BYTE, &memtype);
82     MPI_Type_commit(&memtype);
83
84     free(blocklens);
85     free(disp);
86     return memtype;
87 }
88
89
90 int testtype(MPI_Datatype type, MPI_Offset expected)
91 {
92     MPI_Count size, lb, extent;
93     int nerrors = 0;
94     MPI_Type_size_x(type, &size);
95
96     if (size < 0) {
97         printf("ERROR: type size apparently overflowed integer\n");
98         nerrors++;
99     }
100
101     if (size != expected) {
102         printf("reported type size %lld does not match expected %lld\n", size, expected);
103         nerrors++;
104     }
105
106     MPI_Type_get_true_extent_x(type, &lb, &extent);
107     if (lb != 0) {
108         printf("ERROR: type should have lb of 0, reported %lld\n", lb);
109         nerrors++;
110     }
111
112     if (extent != size) {
113         printf("ERROR: extent should match size, not %lld\n", extent);
114         nerrors++;
115     }
116     return nerrors;
117 }
118
119
120 int main(int argc, char **argv)
121 {
122
123     int nerrors = 0, i;
124     int rank, size;
125     MPI_Init(&argc, &argv);
126     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
127     MPI_Comm_size(MPI_COMM_WORLD, &size);
128
129 #define NR_TYPES 3
130     MPI_Offset expected_sizes[NR_TYPES] = { 1024UL * 1024UL * 2400UL,
131         2346319872,
132         2346319872
133     };
134     MPI_Datatype types[NR_TYPES];
135
136     /* a contig type, itself large, but does not need 8 byte aints */
137     types[0] = make_largexfer_type_struct(expected_sizes[0]);
138     /* struct with addresses out past 2 GiB */
139     types[1] = make_largexfer_type_struct(expected_sizes[1]);
140     /* similar, but with hindexed type */
141     types[2] = make_largexfer_type_hindexed(expected_sizes[2]);
142
143     for (i = 0; i < NR_TYPES; i++) {
144         if (types[i] != MPI_DATATYPE_NULL) {
145             nerrors += testtype(types[i], expected_sizes[i]);
146             MPI_Type_free(&(types[i]));
147         }
148     }
149
150     MPI_Finalize();
151     if (rank == 0) {
152         if (nerrors) {
153             printf("found %d errors\n", nerrors);
154         }
155         else {
156             printf(" No errors\n");
157         }
158     }
159
160     return 0;
161 }