|
| 1 | +# Class common to all types of FAST simulations |
| 2 | +import FastC.PyTree as FastC |
| 3 | +import Converter.PyTree as C |
| 4 | +import Converter.Internal as Internal |
| 5 | +from Apps.App import App |
| 6 | +import Converter.Filter as Filter |
| 7 | +import Converter.Mpi as Cmpi |
| 8 | + |
| 9 | +try: range = xrange |
| 10 | +except: pass |
| 11 | + |
| 12 | +#================================================================================ |
| 13 | +# Redistribue les fichiers in place sans com pour l'instant |
| 14 | +# Change les noeuds procs seulement |
| 15 | +#================================================================================= |
| 16 | +def _distribute(t_in, tc_in, NP=Cmpi.size): |
| 17 | + if isinstance(t_in, str): |
| 18 | + if Cmpi.rank == 0: _distributeFile(t_in, tc_in, NP) |
| 19 | + else: _distributeMem(t_in, tc_in, NP) |
| 20 | + return None |
| 21 | + |
| 22 | +def _distributeFile(t_in, tc_in, NP): |
| 23 | + import Distributor2.PyTree as D2 |
| 24 | + t = Filter.convertFile2SkeletonTree(t_in, maxDepth=3, maxFloatSize=6) |
| 25 | + tc = Filter.convertFile2SkeletonTree(tc_in, maxDepth=3, maxFloatSize=6) |
| 26 | + stats = D2._distribute(tc, NP, algorithm='graph', useCom='ID') |
| 27 | + D2._copyDistribution(t, tc) |
| 28 | + nodes = Internal.getNodesFromName(t, 'proc') |
| 29 | + for n in nodes: |
| 30 | + p = Internal.getPath(t, n) |
| 31 | + Filter.writeNodesFromPaths(t_in, p, n) |
| 32 | + nodes = Internal.getNodesFromName(tc, 'proc') |
| 33 | + for n in nodes: |
| 34 | + p = Internal.getPath(tc, n) |
| 35 | + Filter.writeNodesFromPaths(tc_in, p, n) |
| 36 | + return None |
| 37 | + |
| 38 | +def _distributeMem(t, tc, NP): |
| 39 | + import Distributor2.PyTree as D2 |
| 40 | + tbbc = Cmpi.createBBoxTree(tc) |
| 41 | + stats = D2._distribute(tbbc, NP, algorithm='graph', useCom='ID') |
| 42 | + D2._copyDistribution(tc, tbbc) |
| 43 | + D2._copyDistribution(t, tbbc) |
| 44 | + return None |
| 45 | + |
| 46 | +#================================================== |
| 47 | +# distribution + choix du nombre de coeurs optimum |
| 48 | +#================================================== |
| 49 | +def _distributeOpt(t_in, tc_in, corePerNode=28, nptMaxPerCore=4.e6): |
| 50 | + if isinstance(t_in, str): |
| 51 | + if Cmpi.rank == 0: _distributeOptFile(t_in, tc_in, corePerNode, nptMaxPerCore) |
| 52 | + else: |
| 53 | + #_distributeOptMem(t_in, tc_in, corePerNode, nptMaxPerCore) |
| 54 | + raise ValueError('Not implemented.') |
| 55 | + return None |
| 56 | + |
| 57 | +def _distributeOptFile(t_in, tc_in, corePerNode=28, nptMaxPerCore=4.e6): |
| 58 | + import Distributor2.PyTree as D2 |
| 59 | + t = Filter.convertFile2SkeletonTree(t_in, maxDepth=3, maxFloatSize=6) |
| 60 | + tc = Filter.convertFile2SkeletonTree(tc_in, maxDepth=3, maxFloatSize=6) |
| 61 | + |
| 62 | + nbpts=0.; maxipts=0. |
| 63 | + for zone in Internal.getZones(t): |
| 64 | + ncells = C.getNCells(zone) |
| 65 | + nbpts += ncells |
| 66 | + maxipts = max(maxipts, ncells) |
| 67 | + |
| 68 | + MaxNbProcs=int(nbpts/maxipts)+1 |
| 69 | + |
| 70 | + MinNbProcs=MaxNbProcs |
| 71 | + for nbproc in range(2,MaxNbProcs+1): |
| 72 | + if nbpts*1./nbproc < nptMaxPerCore: MinNbProcs=min(nbproc,MinNbProcs) |
| 73 | + |
| 74 | + print('La distribution sera testee entre %d procs et %d procs.'%(MinNbProcs,MaxNbProcs)) |
| 75 | + |
| 76 | + #MinNbProcs = 140 |
| 77 | + #MaxNbProcs = 140 |
| 78 | + listequ = [] |
| 79 | + varmax = 99. |
| 80 | + NP = MinNbProcs |
| 81 | + for nbproc in range(MinNbProcs,MaxNbProcs+1): |
| 82 | + if nbproc%corePerNode==0: |
| 83 | + print('Distribution sur %s procs.') |
| 84 | + stats = D2._distribute(tc, nbproc, algorithm='graph', useCom='ID') |
| 85 | + listequ.append([nbproc,stats['varMax']]) |
| 86 | + if stats['varMax']<varmax: varmax = stats['varMax']; NP=nbproc |
| 87 | + |
| 88 | + stats = D2._distribute(tc, NP, algorithm='graph', useCom='ID') |
| 89 | + print('Best distribution found on %d procs.'%NP) |
| 90 | + print(stats) |
| 91 | + #D2._printProcStats(t,stats,NP) |
| 92 | + |
| 93 | + D2._copyDistribution(t, tc) |
| 94 | + nodes = Internal.getNodesFromName(t, 'proc') |
| 95 | + for n in nodes: |
| 96 | + p = Internal.getPath(t, n) |
| 97 | + Filter.writeNodesFromPaths(t_in, p, n) |
| 98 | + nodes = Internal.getNodesFromName(tc, 'proc') |
| 99 | + for n in nodes: |
| 100 | + p = Internal.getPath(tc, n) |
| 101 | + Filter.writeNodesFromPaths(tc_in, p, n) |
| 102 | + |
| 103 | + return NP |
| 104 | + |
| 105 | +#================================================================================ |
| 106 | +# en gros, warmup |
| 107 | +#================================================================================ |
| 108 | +def setup(t_in, tc_in, numb, numz, format='single'): |
| 109 | + if Cmpi.size > 1: |
| 110 | + import FastS.Mpi as FastS |
| 111 | + FastC.HOOK = None |
| 112 | + rank = Cmpi.rank; size = Cmpi.size |
| 113 | + else: |
| 114 | + import FastS.PyTree as FastS |
| 115 | + FastC.HOOK = None |
| 116 | + rank = 0; size = 1 |
| 117 | + |
| 118 | + t,tc,ts,graph = FastC.load(t_in, tc_in, split=format) |
| 119 | + |
| 120 | + # Numerics |
| 121 | + FastC._setNum2Zones(t, numz); FastC._setNum2Base(t, numb) |
| 122 | + (t, tc, metrics) = FastS.warmup(t, tc, graph) |
| 123 | + return t, tc, ts, metrics, graph |
| 124 | + |
| 125 | +#============================================================================ |
| 126 | +# Ecrit le resultat |
| 127 | +# t: arbre |
| 128 | +# t_out: fichier de sortie |
| 129 | +# it0: iteration correspondant a la fin du cacul |
| 130 | +# time0: temps correspondant a la fin du calcul |
| 131 | +# format: "single" ou "multiple" |
| 132 | +# compress: si 1, compress le fichier pour le cartesien, 2, compressAll |
| 133 | +# =========================================================================== |
| 134 | +def finalize(t, t_out=None, it0=None, time0=None, format='single', compress=0): |
| 135 | + if it0 is not None: |
| 136 | + Internal.createUniqueChild(t, 'Iteration', 'DataArray_t', value=it0) |
| 137 | + if time0 is not None: |
| 138 | + Internal.createUniqueChild(t, 'Time', 'DataArray_t', value=time0) |
| 139 | + if t_out is not None and isinstance(t_out, str): |
| 140 | + FastC.save(t, t_out, split=format, compress=compress) |
| 141 | + |
| 142 | +#===================================================================================== |
| 143 | +# IN: t_in : nom du fichier t input ou arbre input |
| 144 | +# IN: tc_in: nom du fichier tc input ou arbre tc |
| 145 | +# IN: t_out, tc_out: noms de fichiers ou arbres de sortie |
| 146 | +# IN: numb, numz: les data numeriques |
| 147 | +# IN: NIT: nbre d'iterations |
| 148 | +# format: single ou multiple |
| 149 | +# compress: si 1, compress le fichier de sortie pour le cartesien, 2 compressAll |
| 150 | +#====================================================================================== |
| 151 | +def compute(t_in, tc_in, |
| 152 | + t_out, tc_out, |
| 153 | + numb, numz, |
| 154 | + NIT, |
| 155 | + format='single', compress=0): |
| 156 | + if Cmpi.size > 1: |
| 157 | + import FastS.Mpi as FastS |
| 158 | + rank = Cmpi.rank; size = Cmpi.size |
| 159 | + else: |
| 160 | + import FastS.PyTree as FastS |
| 161 | + rank = 0; size = 1 |
| 162 | + |
| 163 | + t,tc,ts,graph = FastC.load(t_in, tc_in, split=format) |
| 164 | + |
| 165 | + # Numerics |
| 166 | + FastC._setNum2Zones(t, numz); FastC._setNum2Base(t, numb) |
| 167 | + |
| 168 | + (t, tc, metrics) = FastS.warmup(t, tc, graph) |
| 169 | + |
| 170 | + it0 = 0; time0 = 0. |
| 171 | + first = Internal.getNodeFromName1(t, 'Iteration') |
| 172 | + if first is not None: it0 = Internal.getValue(first) |
| 173 | + first = Internal.getNodeFromName1(t, 'Time') |
| 174 | + if first is not None: time0 = Internal.getValue(first) |
| 175 | + time_step = Internal.getNodeFromName(t, 'time_step') |
| 176 | + time_step = Internal.getValue(time_step) |
| 177 | + |
| 178 | + if 'modulo_verif' in numb: moduloVerif = numb['modulo_verif'] |
| 179 | + else: moduloVerif = 200 |
| 180 | + |
| 181 | + for it in range(NIT): |
| 182 | + FastS._compute(t, metrics, it, tc, graph) |
| 183 | + if it%moduloVerif == 0: |
| 184 | + if rank == 0: print('- %d / %d - %f'%(it+it0, NIT+it0, time0)) |
| 185 | + FastS.display_temporal_criteria(t, metrics, it, format='double') |
| 186 | + #if it%50 == 0: |
| 187 | + # import CPlot.PyTree as CPlot |
| 188 | + # CPlot.display(t, dim=2, mode='Scalar', scalarField='Density') |
| 189 | + time0 += time_step |
| 190 | + |
| 191 | + # time stamp |
| 192 | + Internal.createUniqueChild(t, 'Iteration', 'DataArray_t', value=it0+NIT) |
| 193 | + Internal.createUniqueChild(t, 'Time', 'DataArray_t', value=time0) |
| 194 | + if t_out is not None and isinstance(t_out,str): |
| 195 | + FastC.save(t, t_out, split=format, compress=compress) |
| 196 | + if tc_out is not None and isinstance(tc_out,str): |
| 197 | + FastC.save(tc, tc_out, split=format) |
| 198 | + if Cmpi.size > 1: Cmpi.barrier() |
| 199 | + return t, tc |
| 200 | + |
| 201 | +#=============================================================================== |
| 202 | +class Common(App): |
| 203 | + """Preparation et caculs avec le module FastS.""" |
| 204 | + def __init__(self, format=None, numb=None, numz=None): |
| 205 | + App.__init__(self) |
| 206 | + self.__version__ = "0.0" |
| 207 | + self. authors = [ "[email protected]"] |
| 208 | + self.requires(['format', 'numb', 'numz']) |
| 209 | + self.compress = 0 |
| 210 | + # default values |
| 211 | + if format is not None: self.set(format=format) |
| 212 | + else: self.set(format='single') |
| 213 | + if numb is not None: self.set(numb=numb) |
| 214 | + if numz is not None: self.set(numz=numz) |
| 215 | + |
| 216 | + # Compute nit iterations |
| 217 | + # peut etre lance en sequentiel ou en parallele |
| 218 | + def compute(self, t_in, tc_in, t_out, nit, tc_out=None): |
| 219 | + numb = self.data['numb'] |
| 220 | + numz = self.data['numz'] |
| 221 | + compress = self.compress |
| 222 | + return compute(t_in, tc_in, t_out, tc_out, |
| 223 | + numb, numz, |
| 224 | + nit, |
| 225 | + format=self.data['format'], |
| 226 | + compress=compress) |
| 227 | + |
| 228 | + # warm up et all |
| 229 | + def setup(self, t_in, tc_in): |
| 230 | + numb = self.data['numb'] |
| 231 | + numz = self.data['numz'] |
| 232 | + return setup(t_in, tc_in, numb, numz, self.data['format']) |
| 233 | + |
| 234 | + # Ecrit le fichier de sortie |
| 235 | + def finalize(self, t_out=None, it0=None, time0=None): |
| 236 | + finalize(t_out, it0, time0, self.data['format']) |
| 237 | + |
| 238 | + # distribue fichiers ou en memoire |
| 239 | + def _distribute(self, t_in, tc_in, NP=Cmpi.size): |
| 240 | + return _distribute(t_in, tc_in, NP) |
| 241 | + |
| 242 | + # distribue fichiers ou en memoire, trouve le NP optimal |
| 243 | + def _distributeOpt(self, t_in, tc_in, corePerNode=28, nptMaxPerCore=4.e6): |
| 244 | + return _distributeOpt(t_in, tc_in, corePerNode, nptMaxPerCore) |
0 commit comments