[10335] | 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() |
---|