Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Update comm, datatype from mpich trunk
[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 accomodate 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     } else {
34         if (sizeof(MPI_Aint) <= sizeof(int)) {
35             return MPI_DATATYPE_NULL;
36         }
37        /* struct type: some number of chunks plus remaining bytes tacked
38          * on at end */
39         int lens[] = {chunk_count, remainder};
40         MPI_Aint disp[] = {0, (MPI_Aint) typechunk_size * (MPI_Aint)chunk_count};
41         MPI_Datatype types[] = {chunktype, MPI_BYTE};
42
43         MPI_Type_struct(2, lens, disp, types, &memtype);
44         MPI_Type_free(&chunktype);
45     }
46     MPI_Type_commit(&memtype);
47     return memtype;
48 }
49 static MPI_Datatype make_largexfer_type_hindexed(MPI_Offset nbytes)
50 {
51     int i, count;
52     int chunk_size = 1024*1024;
53     int *blocklens;
54     MPI_Aint *disp;
55     MPI_Datatype memtype;
56
57     /* need to cook up a new datatype to accomodate large datatypes */
58     /* Does require 8 byte MPI_Aint, which should have been checked for earlier
59      */
60
61     if (sizeof(MPI_Aint) <= sizeof(int)) {
62         return MPI_DATATYPE_NULL;
63     }
64     
65     /* ceiling division */
66     count = 1 + ((nbytes -1) / chunk_size );
67
68     blocklens = calloc(count, sizeof(int));
69     disp = calloc(count, sizeof(MPI_Aint));
70
71
72     for (i=0; i<(count-1); i++) {
73         blocklens[i] = chunk_size;
74         disp[i] = (MPI_Aint)chunk_size*i;
75     }
76     blocklens[count-1] = nbytes-((MPI_Aint)chunk_size*i);
77     disp[count-1] = (MPI_Aint)chunk_size*(count-1);
78
79     MPI_Type_create_hindexed(count, blocklens, disp, MPI_BYTE, &memtype);
80     MPI_Type_commit(&memtype);
81
82     return memtype;
83 }
84
85
86 int testtype(MPI_Datatype type, MPI_Offset expected) {
87     MPI_Count size, lb, extent;
88     int nerrors=0;
89     MPI_Type_size_x(type, &size);
90
91     if (size < 0)  {
92         printf("ERROR: type size apparently overflowed integer\n");
93         nerrors++;
94     }
95
96     if (size != expected) {
97         printf("reported type size %lld does not match expected %lld\n",
98                 size, expected);
99         nerrors++;
100     }
101
102     MPI_Type_get_true_extent_x(type, &lb, &extent);
103     if (lb != 0) {
104         printf("ERROR: type should have lb of 0, reported %lld\n", lb);
105         nerrors ++;
106     }
107
108     if (extent != size) { 
109         printf("ERROR: extent should match size, not %lld\n", extent);
110         nerrors ++;
111     }
112     return nerrors;
113 }
114
115
116 int main(int argc, char **argv)
117 {
118
119     int nerrors=0, i;
120     int rank, size;
121     MPI_Init(&argc, &argv);
122     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
123     MPI_Comm_size(MPI_COMM_WORLD, &size);
124
125 #define NR_TYPES 3
126     MPI_Offset expected_sizes[NR_TYPES] = {1024UL*1024UL*2400UL,
127         2346319872,
128         2346319872};
129     MPI_Datatype types[NR_TYPES];
130
131     /* a contig type, itself large, but does not need 8 byte aints */
132     types[0] = make_largexfer_type_struct(expected_sizes[0]);
133     /* struct with addresses out past 2 GiB */
134     types[1] = make_largexfer_type_struct(expected_sizes[1]);
135     /* similar, but with hindexed type */
136     types[2] = make_largexfer_type_hindexed(expected_sizes[2]);
137
138     for (i=0; i<NR_TYPES; i++) {
139         if (types[i] != MPI_DATATYPE_NULL) {
140                 nerrors += testtype(types[i], expected_sizes[i]);
141                 MPI_Type_free(&(types[i]));
142         }
143     }
144
145     MPI_Finalize();
146     if (rank == 0) {
147         if (nerrors) {
148             printf("found %d errors\n", nerrors);
149         } else {
150             printf(" No errors\n");
151         }
152     }
153
154     return 0;
155 }