3 # Copyright 2021-2022. The MBI project. All rights reserved.
4 # This program is free software; you can redistribute it and/or modify it under the terms of the license (GNU GPL).
8 import generator_utils as gen
10 template = """// @{generatedby}@
11 /* ///////////////////////// The MPI Bugs Initiative ////////////////////////
15 Description: @{shortdesc}@
18 Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
22 P2P!nonblocking: Lacking
23 P2P!persistent: Lacking
24 COLL!basic: @{collfeature}@
25 COLL!nonblocking: @{icollfeature}@
26 COLL!persistent: Lacking
36 ////////////////////// End of MBI headers /////////////////// */
44 int main(int argc, char **argv) {
49 MPI_Init(&argc, &argv);
50 MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
51 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
52 printf("Hello from rank %d \\n", rank);
55 printf("MBI ERROR: This test needs at least 2 processes to produce a bug.\\n");
57 MPI_Comm newcom = MPI_COMM_WORLD;
58 MPI_Datatype type = MPI_INT;
61 int dbs = sizeof(int)*nprocs; /* Size of the dynamic buffers for alltoall and friends */
65 if (@{change_cond}@) {
66 @{operation1a}@ /* MBIERROR1 */
71 @{operation1b}@ /* MBIERROR2 */
81 printf("Rank %d finished normally\\n", rank);
86 for c1 in gen.coll + gen.icoll + gen.ibarrier:
87 for c2 in gen.coll + gen.icoll + gen.ibarrier:
89 patterns = {'c1': c1, 'c2': c2}
90 patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
91 patterns['collfeature'] = 'Yes' if c1 in gen.coll or c2 in gen.coll else 'Lacking'
92 patterns['icollfeature'] = 'Yes' if c1 in gen.icoll + gen.ibarrier or c2 in gen.icoll + gen.ibarrier else 'Lacking'
95 patterns['init1'] = gen.init[c1]("1")
96 patterns['init2'] = gen.init[c2]("2")
97 patterns['fini1a'] = gen.fini[c1]("1")
98 patterns['fini2a'] = gen.fini[c2]("2")
99 patterns['fini1b'] = gen.fini[c1]("1")
100 patterns['fini2b'] = gen.fini[c2]("2")
101 patterns['free1'] = gen.free[c1]("1")
102 patterns['free2'] = gen.free[c2]("2")
103 patterns['operation1a'] = gen.operation[c1]("1")
104 patterns['operation1b'] = gen.operation[c1]("1")
105 patterns['operation2a'] = gen.operation[c2]("2")
106 patterns['operation2b'] = gen.operation[c2]("2")
107 patterns['change_cond'] = 'rank % 2'
108 shortdesc = ' collective ordering'
111 # Generate the correct code using the same collective twice
112 replace = patterns.copy()
113 replace['shortdesc'] = 'Correct' + shortdesc
114 replace['longdesc'] = f'All ranks call {c1} twice'
115 replace['outcome'] = 'OK'
116 replace['errormsg'] = ''
117 gen.make_file(template, f'CallOrdering_{c1}_{c2}_ok.c', replace)
118 # Generate the correct code using the collective once
119 replace = patterns.copy()
120 replace['shortdesc'] = 'Correct' + shortdesc
121 replace['longdesc'] = f'All ranks call {c1} once'
122 replace['outcome'] = 'OK'
123 replace['errormsg'] = ''
124 replace['init2'] = ''
125 replace['operation2a'] = ''
126 replace['operation2b'] = ''
127 replace['fini2a'] = ''
128 replace['fini2b'] = ''
129 replace['free2'] = ''
130 gen.make_file(template, f'CallOrdering_{c1}_ok.c', replace)
132 # Generate the correct ordering with two different collectives
133 replace = patterns.copy()
134 replace['shortdesc'] = 'Correct' + shortdesc
135 replace['longdesc'] = f'All ranks call {c1} and then {c2}'
136 replace['outcome'] = 'OK'
137 replace['errormsg'] = ''
138 gen.make_file(template, f'CallOrdering_{c1}_{c2}_ok.c', replace)
139 # Generate the incorrect ordering with two different collectives
140 replace = patterns.copy()
141 replace['shortdesc'] = 'Incorrect' + shortdesc
142 replace['longdesc'] = f'Odd ranks call {c1} and then {c2} while even ranks call these collectives in the other order'
143 replace['outcome'] = 'ERROR: CallMatching'
144 replace['errormsg'] = 'Collective mistmatch. @{c1}@ at @{filename}@:@{line:MBIERROR1}@ is matched with @{c2}@ line @{filename}@:@{line:MBIERROR2}@.'
145 replace['operation1b'] = gen.operation[c2]("2") # Inversion
146 replace['operation2b'] = gen.operation[c1]("1")
147 replace['fini1a'] = gen.fini[c1]("1") # Inversion
148 replace['fini2a'] = gen.fini[c2]("2")
149 replace['fini1b'] = gen.fini[c2]("2") # Inversion
150 replace['fini2b'] = gen.fini[c1]("1")
151 replace['free1'] = gen.free[c2]("2")
152 replace['free2'] = gen.free[c1]("1")
154 gen.make_file(template, f'CallOrdering_{c1}_{c2}_nok.c', replace)
156 # Generate the incorrect ordering with one collective
157 replace = patterns.copy()
158 replace['shortdesc'] = 'Incorrect' + shortdesc
159 replace['longdesc'] = f'Odd ranks call {c1} while even ranks do not call any collective'
160 replace['outcome'] = 'ERROR: CallMatching'
161 replace['errormsg'] = 'Collective mistmatch. @{c1}@ at @{filename}@:@{line:MBIERROR1}@ is not matched.'
162 replace['operation1b'] = '' # Remove functions
163 replace['operation2b'] = ''
164 replace['operation2a'] = ''
165 replace['init2'] = ''
166 replace['fini1b'] = ''
167 replace['fini2a'] = ''
168 replace['fini2b'] = ''
169 replace['free1'] = gen.free[c1]("1")
170 replace['free2'] = ''
171 gen.make_file(template, f'CallOrdering_{c1}_none_nok.c', replace)
172 # Generate a correct ordering with a conditional not depending on ranks
173 replace = patterns.copy()
174 replace['shortdesc'] = 'Correct' + shortdesc
175 replace['longdesc'] = f'All ranks call {c1}'
176 replace['outcome'] = 'OK'
177 replace['errormsg'] = ''
178 replace['change_cond'] = 'nprocs<256'
179 replace['operation1b'] = '' # Remove functions
180 replace['operation2b'] = ''
181 replace['operation2a'] = ''
182 replace['init2'] = ''
183 replace['fini1b'] = ''
184 replace['fini2a'] = ''
185 replace['fini2b'] = ''
186 replace['free1'] = gen.free[c1]("1")
187 replace['free2'] = ''
188 gen.make_file(template, f'CallOrdering_{c1}_none_ok.c', replace)