1 | """ |
---|
2 | script to sort and select processor layout from MPP_PREP output |
---|
3 | wrote by P. Mathiot 10/2018 |
---|
4 | """ |
---|
5 | |
---|
6 | # import module |
---|
7 | from __future__ import print_function |
---|
8 | import argparse |
---|
9 | import sys |
---|
10 | |
---|
11 | # define class layout |
---|
12 | class layout(object): |
---|
13 | """ |
---|
14 | Class containing all the information about a specific model layout |
---|
15 | |
---|
16 | Output: |
---|
17 | self.jpnij = (i domain along i dimension, j domain along j dimension, total number of domain (land+ocean)) |
---|
18 | self.nproc = (total number of domain (land+ocean), n ocean domain, nland domain) |
---|
19 | self.jpij = (dimension along i, dimension along j) of a domain |
---|
20 | self.ratio = (total computed point, overhead, ratio computed point / global) |
---|
21 | """ |
---|
22 | def __init__(self, txtlst): |
---|
23 | """ |
---|
24 | Initialisation of a layout class object: |
---|
25 | |
---|
26 | Input: list of string containing 1 layout description |
---|
27 | extracted from the processor layout file |
---|
28 | """ |
---|
29 | self.jpnij = extract_jpnij(txtlst) # (jpni, jpnj, jpnij) |
---|
30 | self.nproc = extract_nproc(txtlst) # (ntot, noce, nland) |
---|
31 | self.jpij = extract_jpij(txtlst) # (jpi , jpj) |
---|
32 | self.ratio = extract_point(txtlst) # (total computed point, overhead, ratio computed point / global) |
---|
33 | |
---|
34 | def test_criterion(self, rmax, nocemin, nocemax): |
---|
35 | """ |
---|
36 | function to decide if yes or no a specific layout has to be selected |
---|
37 | Input: |
---|
38 | float rmax: maximal ratio (computed/global) accepted |
---|
39 | int nocemin and nocemax: range of number of ocean processor accepted |
---|
40 | |
---|
41 | output: logical |
---|
42 | """ |
---|
43 | if ( nocemin <= self.nproc[1] <= nocemax ) and ( self.ratio[2] <= rmax ): |
---|
44 | return True |
---|
45 | else: |
---|
46 | return False |
---|
47 | |
---|
48 | def print_layout(self, cidx): |
---|
49 | """ |
---|
50 | function to print specific information about a specific layout |
---|
51 | """ |
---|
52 | print( 'Domain decomposition {}'.format(cidx) ) |
---|
53 | print( 'domain decomposition (jpni, jpnj) = {}'.format((self.jpnij[0], self.jpnij[1])) ) |
---|
54 | print( 'number of ocean domain = {}'.format(self.nproc[1]) ) |
---|
55 | print( 'ratio computed/global = {}'.format(self.ratio[2]) ) |
---|
56 | print( 'domain size (jpi, jpj) = {}'.format(self.jpij) ) |
---|
57 | print('') |
---|
58 | |
---|
59 | # define sorting function |
---|
60 | def noce_proc(elem): |
---|
61 | """ |
---|
62 | function used as key to sort list of layout |
---|
63 | by number of ocean domain in the list sorting algorithm |
---|
64 | """ |
---|
65 | return elem.nproc[1] |
---|
66 | |
---|
67 | def ratio_proc(elem): |
---|
68 | """ |
---|
69 | function used as key to sort list of layout |
---|
70 | by ratio (computed/global) in the list sorting algorithm |
---|
71 | """ |
---|
72 | return elem.ratio[2] |
---|
73 | |
---|
74 | def jpij_proc(elem): |
---|
75 | """ |
---|
76 | function used as key to sort list of layout |
---|
77 | by domain size in the list sorting algorithm |
---|
78 | """ |
---|
79 | return elem.jpij[0]*elem.jpij[1] |
---|
80 | |
---|
81 | # txt extraction function to feed class layout |
---|
82 | def extract_jpnij(txtlst): |
---|
83 | """ |
---|
84 | function to extract total number of domain |
---|
85 | for a specific domain layout txt output |
---|
86 | |
---|
87 | Input: list of string containing 1 layout description |
---|
88 | extracted from the processor layout file |
---|
89 | |
---|
90 | Output: tuple (jpni, jpnj, jpni*jpnj) |
---|
91 | """ |
---|
92 | jpnij = int(txtlst[1].split()[-1]) |
---|
93 | ctmp = txtlst[3].split() |
---|
94 | jpni = int(ctmp[1]) |
---|
95 | jpnj = int(ctmp[3]) |
---|
96 | return (jpni, jpnj, jpnij) |
---|
97 | |
---|
98 | def extract_nproc(txtlst): |
---|
99 | """ |
---|
100 | function to extract total number of ocean domain |
---|
101 | for a specific domain layout txt output |
---|
102 | |
---|
103 | Input: list of string containing 1 layout description |
---|
104 | extracted from the processor layout file |
---|
105 | |
---|
106 | Output: tuple (jpni*jpnj, n oce domain, n land domain) |
---|
107 | """ |
---|
108 | ntot = int(txtlst[1].split()[-1]) |
---|
109 | noce = int(txtlst[5].split()[-1]) |
---|
110 | nland = int(txtlst[6].split()[-1]) |
---|
111 | return (ntot, noce, nland) |
---|
112 | |
---|
113 | def extract_jpij(txtlst): |
---|
114 | """ |
---|
115 | function to extract domain dimension |
---|
116 | for a specific domain layout txt output |
---|
117 | |
---|
118 | Input: list of string containing 1 layout description |
---|
119 | extracted from the processor layout file |
---|
120 | |
---|
121 | Output: tuple (jpi, jpj) |
---|
122 | """ |
---|
123 | ctmp = txtlst[4].split() |
---|
124 | jpi = int(ctmp[1]) |
---|
125 | jpj = int(ctmp[3]) |
---|
126 | return (jpi, jpj) |
---|
127 | |
---|
128 | def extract_point(txtlst): |
---|
129 | """ |
---|
130 | function to extract ration (computed/global) |
---|
131 | for a specific domain layout txt output |
---|
132 | |
---|
133 | Input: list of string containing 1 layout description |
---|
134 | extracted from the processor layout file |
---|
135 | |
---|
136 | Output: tuple (total number of point, overhead, ratio (computed/global)) |
---|
137 | """ |
---|
138 | npoint = int(txtlst[13].split()[-1]) |
---|
139 | noverh = int(txtlst[14].split()[-1]) |
---|
140 | ratio = float(txtlst[15].split()[-1]) |
---|
141 | return (npoint, noverh, ratio) |
---|
142 | |
---|
143 | # main |
---|
144 | def main(): |
---|
145 | """ |
---|
146 | script to sort and select processor layout from MPP_PREP output based on user constrains |
---|
147 | """ |
---|
148 | |
---|
149 | parser = argparse.ArgumentParser() |
---|
150 | parser.add_argument("-f", metavar='layout_file' , help="names of domain layout file to sort", type=str, nargs=1, required=True) |
---|
151 | parser.add_argument("--rmax", metavar='max_ratio' , help="max ratio allowed (computed/global)", type=float, nargs=1, required=True) |
---|
152 | parser.add_argument("--noce", metavar='min/max_noce' , help="min and max number of ocean domain allowed", type=int, nargs=2, required=True) |
---|
153 | |
---|
154 | args = parser.parse_args() |
---|
155 | |
---|
156 | # read file |
---|
157 | filein = args.f[0] |
---|
158 | fid = open(filein,"r") #opens file with name of "test.txt" |
---|
159 | txtdata = [] |
---|
160 | for cline in fid: |
---|
161 | txtdata.extend([cline]) |
---|
162 | |
---|
163 | # skip header and tail of file |
---|
164 | txtdata = txtdata[4:-20] |
---|
165 | |
---|
166 | # loop on different domain decomposition |
---|
167 | ilinepl = 17 # number of line of a specific decomposition |
---|
168 | ilayout = 0 |
---|
169 | lst_layout = [] |
---|
170 | ratio_min = 9999.0 |
---|
171 | noce_min = 9999999 |
---|
172 | noce_max = 0 |
---|
173 | for iline in range(0, len(txtdata)): |
---|
174 | if iline % ilinepl == 0: |
---|
175 | # initialise layout |
---|
176 | conf_layout = layout( txtdata[iline:iline+ilinepl] ) |
---|
177 | ratio_min = min( conf_layout.ratio[2], ratio_min ) |
---|
178 | noce_min = min( conf_layout.nproc[1], noce_min ) |
---|
179 | noce_max = max( conf_layout.nproc[1], noce_max ) |
---|
180 | |
---|
181 | # select layout based on condition |
---|
182 | if conf_layout.test_criterion(args.rmax[0], args.noce[0], args.noce[1]): |
---|
183 | ilayout = ilayout + 1 |
---|
184 | lst_layout.extend([conf_layout]) |
---|
185 | |
---|
186 | if lst_layout == []: |
---|
187 | print('') |
---|
188 | print( 'E R R O R: constrains are too strong, no domain are found' ) |
---|
189 | print('') |
---|
190 | if ratio_min > args.rmax[0] : |
---|
191 | print( 'min ratio is {} and you ask for a ratio smaller than {}'.format(ratio_min, args.rmax[0]) ) |
---|
192 | if noce_min > args.noce[1] : |
---|
193 | print( 'min ocean proc is {} and you ask for a number of ocean proc lower than {}'.format(noce_min, args.noce[1]) ) |
---|
194 | if noce_max < args.noce[0] : |
---|
195 | print( 'max ocean proc is {} and you ask for a number of ocean proc larger than {}'.format(noce_max, args.noce[0]) ) |
---|
196 | print('') |
---|
197 | sys.exit() |
---|
198 | |
---|
199 | lst_layout.sort(key=noce_proc) |
---|
200 | for idx, ilayout in enumerate(lst_layout): |
---|
201 | ilayout.print_layout(str(idx)) |
---|
202 | |
---|
203 | print( '=====================================================================' ) |
---|
204 | print('') |
---|
205 | print( 'Among the layouts fitting the constraint on : ratio (computed/global) < {} and {} <= number of ocean domain <= {}' \ |
---|
206 | .format(args.rmax[0], args.noce[0], args.noce[1]) ) |
---|
207 | print('') |
---|
208 | print( ' 3 layouts are highlighted : ' ) |
---|
209 | print('') |
---|
210 | lst_layout.sort(key=ratio_proc) |
---|
211 | lst_layout[0].print_layout('SMALLEST RATIO') |
---|
212 | # |
---|
213 | lst_layout.sort(key=noce_proc) |
---|
214 | lst_layout[-1].print_layout('LARGEST NUMBER OF OCEAN DOMAINS') |
---|
215 | # |
---|
216 | lst_layout.sort(key=jpij_proc) |
---|
217 | lst_layout[0].print_layout('SMALLEST COMPUTED DOMAIN') |
---|
218 | |
---|
219 | if __name__ == "__main__": |
---|
220 | main() |
---|