Package PyFoam :: Package Applications :: Module Benchmark
[hide private]
[frames] | no frames]

Source Code for Module PyFoam.Applications.Benchmark

  1  #  ICE Revision: $Id: /local/openfoam/Python/PyFoam/PyFoam/Applications/Benchmark.py 7660 2012-01-07T16:44:40.128256Z bgschaid  $  
  2  """ 
  3  Class that implements pyFoamBenchmark 
  4  """ 
  5   
  6  from PyFoamApplication import PyFoamApplication 
  7   
  8  from fnmatch import fnmatch 
  9   
 10  import sys,string,ConfigParser 
 11   
 12  from os import path,uname 
 13  from time import time,localtime,asctime 
 14  from PyFoam.Execution.BasicRunner import BasicRunner 
 15  from PyFoam.FoamInformation import foamTutorials 
 16  from PyFoam.RunDictionary.SolutionDirectory import SolutionDirectory 
 17  from PyFoam.RunDictionary.SolutionFile import SolutionFile 
 18  from PyFoam.RunDictionary.ParameterFile import ParameterFile 
 19  from PyFoam.RunDictionary.BlockMesh import BlockMesh 
 20  from PyFoam.Execution.ParallelExecution import LAMMachine 
 21  from PyFoam.Basics.Utilities import execute,remove,rmtree 
 22  from PyFoam.Basics.CSVCollection import CSVCollection 
 23  from PyFoam.FoamInformation import oldAppConvention as oldApp 
 24   
25 -class Benchmark(PyFoamApplication):
26 - def __init__(self,args=None):
27 description="""\ 28 Runs a set of benchmarks specified in a config files 29 """ 30 PyFoamApplication.__init__(self,args=args,description=description,usage="%prog [options] <specification>",interspersed=True,nr=1)
31
32 - def addOptions(self):
33 self.parser.add_option("--nameAddition", 34 action="store", 35 dest="nameAddition", 36 default=None, 37 help="Addition to the name that helps to distinguish different runs of the same configuration") 38 self.parser.add_option("--removeCases", 39 action="store_true", 40 dest="removeCases", 41 default=False, 42 help="Remove the case directories and log files for all successfully run cases") 43 self.parser.add_option("--exclude-cases", 44 action="append", 45 default=None, 46 dest="excases", 47 help="Cases which should not be processed (pattern, can be used more than once)") 48 self.parser.add_option("--cases", 49 action="append", 50 default=None, 51 dest="cases", 52 help="Cases which should be processed (pattern, can be used more than once)")
53
54 - def run(self):
55 config=ConfigParser.ConfigParser() 56 files=self.parser.getArgs() 57 58 good=config.read(files) 59 # will work with 2.4 60 # if len(good)!=len(files): 61 # print "Problem while trying to parse files",files 62 # print "Only ",good," could be parsed" 63 # sys.exit(-1) 64 65 benchName=config.get("General","name") 66 if self.opts.nameAddition!=None: 67 benchName+="_"+self.opts.nameAddition 68 if self.opts.foamVersion!=None: 69 benchName+="_v"+self.opts.foamVersion 70 71 isParallel=config.getboolean("General","parallel") 72 lam=None 73 74 if isParallel: 75 nrCpus=config.getint("General","nProcs") 76 machineFile=config.get("General","machines") 77 if not path.exists(machineFile): 78 self.error("Machine file ",machineFile,"needed for parallel run") 79 lam=LAMMachine(machineFile,nr=nrCpus) 80 if lam.cpuNr()>nrCpus: 81 self.error("Wrong number of CPUs: ",lam.cpuNr()) 82 83 print "Running parallel on",lam.cpuNr(),"CPUs" 84 85 if config.has_option("General","casesDirectory"): 86 casesDirectory=path.expanduser(config.get("General","casesDirectory")) 87 else: 88 casesDirectory=foamTutorials() 89 90 if not path.exists(casesDirectory): 91 self.error("Directory",casesDirectory,"needed with the benchmark cases is missing") 92 else: 93 print "Using cases from directory",casesDirectory 94 95 benchCases=[] 96 config.remove_section("General") 97 98 for sec in config.sections(): 99 print "Reading: ",sec 100 skipIt=False 101 skipReason="" 102 if config.has_option(sec,"skip"): 103 skipIt=config.getboolean(sec,"skip") 104 skipReason="Switched off in file" 105 if self.opts.excases!=None and not skipIt: 106 for p in self.opts.excases: 107 if fnmatch(sec,p): 108 skipIt=True 109 skipReason="Switched off by pattern '"+p+"'" 110 if self.opts.cases!=None: 111 for p in self.opts.cases: 112 if fnmatch(sec,p): 113 skipIt=False 114 skipReason="" 115 116 if skipIt: 117 print "Skipping case ..... Reason:"+skipReason 118 continue 119 sol=config.get(sec,"solver") 120 cas=config.get(sec,"case") 121 pre=eval(config.get(sec,"prepare")) 122 preCon=[] 123 if config.has_option(sec,"preControlDict"): 124 preCon=eval(config.get(sec,"preControlDict")) 125 con=eval(config.get(sec,"controlDict")) 126 bas=config.getfloat(sec,"baseline") 127 wei=config.getfloat(sec,"weight") 128 add=[] 129 if config.has_option(sec,"additional"): 130 add=eval(config.get(sec,"additional")) 131 print "Adding: ", add 132 util=[] 133 if config.has_option(sec,"utilities"): 134 util=eval(config.get(sec,"utilities")) 135 print "Utilities: ", util 136 nr=99999 137 if config.has_option(sec,"nr"): 138 nr=eval(config.get(sec,"nr")) 139 sp=None 140 if config.has_option(sec,"blockSplit"): 141 sp=eval(config.get(sec,"blockSplit")) 142 toRm=[] 143 if config.has_option(sec,"filesToRemove"): 144 toRm=eval(config.get(sec,"filesToRemove")) 145 setInit=[] 146 if config.has_option(sec,"setInitial"): 147 setInit=eval(config.get(sec,"setInitial")) 148 149 parallelOK=False 150 if config.has_option(sec,"parallelOK"): 151 parallelOK=config.getboolean(sec,"parallelOK") 152 153 deMet=["metis"] 154 if config.has_option(sec,"decomposition"): 155 deMet=config.get(sec,"decomposition").split() 156 157 if deMet[0]=="metis": 158 pass 159 elif deMet[0]=="simple": 160 if len(deMet)<2: 161 deMet.append(0) 162 else: 163 deMet[1]=int(deMet[1]) 164 else: 165 print "Unimplemented decomposition method",deMet[0],"switching to metis" 166 deMet=["metis"] 167 168 if isParallel==False or parallelOK==True: 169 if path.exists(path.join(casesDirectory,sol,cas)): 170 benchCases.append( (nr,sec,sol,cas,pre,con,preCon,bas,wei,add,util,sp,toRm,setInit,deMet) ) 171 else: 172 print "Skipping",sec,"because directory",path.join(casesDirectory,sol,cas),"could not be found" 173 else: 174 print "Skipping",sec,"because not parallel" 175 176 benchCases.sort() 177 178 parallelString="" 179 if isParallel: 180 parallelString=".cpus="+str(nrCpus) 181 182 resultFile=open("Benchmark."+benchName+"."+uname()[1]+parallelString+".results","w") 183 184 totalSpeedup=0 185 minSpeedup=None 186 maxSpeedup=None 187 totalWeight =0 188 runsOK=0 189 currentEstimate = 1. 190 191 print "\nStart Benching\n" 192 193 csv=CSVCollection("Benchmark."+benchName+"."+uname()[1]+parallelString+".csv") 194 195 # csvHeaders=["description","solver","case","caseDir","base", 196 # "benchmark","machine","arch","cpus","os","version", 197 # "wallclocktime","cputime","cputimeuser","cputimesystem","maxmemory","cpuusage","speedup"] 198 199 for nr,description,solver,case,prepare,control,preControl,base,weight,additional,utilities,split,toRemove,setInit,decomposition in benchCases: 200 # control.append( ("endTime",-2000) ) 201 print "Running Benchmark: ",description 202 print "Solver: ",solver 203 print "Case: ",case 204 caseName=solver+"_"+case+"_"+benchName+"."+uname()[1]+".case" 205 print "Short name: ",caseName 206 caseDir=caseName+".runDir" 207 208 csv["description"]=description 209 csv["solver"]=solver 210 csv["case"]=case 211 csv["caseDir"]=caseDir 212 csv["base"]=base 213 214 csv["benchmark"]=benchName 215 csv["machine"]=uname()[1] 216 csv["arch"]=uname()[4] 217 if lam==None: 218 csv["cpus"]=1 219 else: 220 csv["cpus"]=lam.cpuNr() 221 csv["os"]=uname()[0] 222 csv["version"]=uname()[2] 223 224 workDir=path.realpath(path.curdir) 225 226 orig=SolutionDirectory(path.join(casesDirectory,solver,case), 227 archive=None, 228 paraviewLink=False) 229 for a in additional+utilities: 230 orig.addToClone(a) 231 orig.cloneCase(path.join(workDir,caseDir)) 232 233 if oldApp(): 234 argv=[solver,workDir,caseDir] 235 else: 236 argv=[solver,"-case",path.join(workDir,caseDir)] 237 238 run=BasicRunner(silent=True,argv=argv,logname="BenchRunning",lam=lam) 239 runDir=run.getSolutionDirectory() 240 controlFile=ParameterFile(runDir.controlDict()) 241 242 for name,value in preControl: 243 print "Setting parameter",name,"to",value,"in controlDict" 244 controlFile.replaceParameter(name,value) 245 246 for rm in toRemove: 247 fn=path.join(caseDir,rm) 248 print "Removing file",fn 249 remove(fn) 250 251 for field,bc,val in setInit: 252 print "Setting",field,"on",bc,"to",val 253 SolutionFile(runDir.initialDir(),field).replaceBoundary(bc,val) 254 255 oldDeltaT=controlFile.replaceParameter("deltaT",0) 256 257 for u in utilities: 258 print "Building utility ",u 259 execute("wmake 2>&1 >%s %s" % (path.join(caseDir,"BenchCompile."+u),path.join(caseDir,u))) 260 261 print "Preparing the case: " 262 if lam!=None: 263 prepare=prepare+[("decomposePar","")] 264 if decomposition[0]=="metis": 265 lam.writeMetis(SolutionDirectory(path.join(workDir,caseDir))) 266 elif decomposition[0]=="simple": 267 lam.writeSimple(SolutionDirectory(path.join(workDir,caseDir)),decomposition[1]) 268 269 if split: 270 print "Splitting the mesh:",split 271 bm=BlockMesh(runDir.blockMesh()) 272 bm.refineMesh(split) 273 274 for pre,post in prepare: 275 print "Doing ",pre," ...." 276 post=post.replace("%case%",caseDir) 277 if oldApp(): 278 args=string.split("%s %s %s %s" % (pre,workDir,caseDir,post)) 279 else: 280 args=string.split("%s -case %s %s" % (pre,path.join(workDir,caseDir),post)) 281 util=BasicRunner(silent=True,argv=args,logname="BenchPrepare_"+pre) 282 util.start() 283 284 controlFile.replaceParameter("deltaT",oldDeltaT) 285 286 # control.append(("endTime",-1000)) 287 for name,value in control: 288 print "Setting parameter",name,"to",value,"in controlDict" 289 controlFile.replaceParameter(name,value) 290 291 print "Starting at ",asctime(localtime(time())) 292 print " Baseline is %f, estimated speedup %f -> estimated end at %s " % (base,currentEstimate,asctime(localtime(time()+base/currentEstimate))) 293 print "Running the case ...." 294 run.start() 295 296 speedup=None 297 cpuUsage=0 298 speedupOut=-1 299 300 try: 301 speedup=base/run.run.wallTime() 302 cpuUsage=100.*run.run.cpuTime()/run.run.wallTime() 303 except ZeroDivisionError: 304 print "Division by Zero: ",run.run.wallTime() 305 306 if not run.runOK(): 307 print "\nWARNING!!!!" 308 print "Run had a problem, not using the results. Check the log\n" 309 speedup=None 310 311 if speedup!=None: 312 speedupOut=speedup 313 314 totalSpeedup+=speedup*weight 315 totalWeight +=weight 316 runsOK+=1 317 if maxSpeedup==None: 318 maxSpeedup=speedup 319 elif speedup>maxSpeedup: 320 maxSpeedup=speedup 321 if minSpeedup==None: 322 minSpeedup=speedup 323 elif speedup<minSpeedup: 324 minSpeedup=speedup 325 326 print "Wall clock: ",run.run.wallTime() 327 print "Speedup: ",speedup," (Baseline: ",base,")" 328 print "CPU Time: ",run.run.cpuTime() 329 print "CPU Time User: ",run.run.cpuUserTime() 330 print "CPU Time System: ",run.run.cpuSystemTime() 331 print "Memory: ",run.run.usedMemory() 332 print "CPU Usage: %6.2f%%" % (cpuUsage) 333 334 csv["wallclocktime"]=run.run.wallTime() 335 csv["cputime"]=run.run.cpuTime() 336 csv["cputimeuser"]=run.run.cpuUserTime() 337 csv["cputimesystem"]=run.run.cpuSystemTime() 338 csv["maxmemory"]=run.run.usedMemory() 339 csv["cpuusage"]=cpuUsage 340 if speedup!=None: 341 csv["speedup"]=speedup 342 else: 343 csv["speedup"]="##" 344 345 csv.write() 346 347 resultFile.write("Case %s WallTime %g CPUTime %g UserTime %g SystemTime %g Memory %g MB Speedup %g\n" %(caseName,run.run.wallTime(),run.run.cpuTime(),run.run.cpuUserTime(),run.run.cpuSystemTime(),run.run.usedMemory(),speedupOut)) 348 349 resultFile.flush() 350 351 if speedup!=None: 352 currentEstimate=totalSpeedup/totalWeight 353 354 if self.opts.removeCases: 355 print "Clearing case", 356 if speedup==None: 357 print "not ... because it failed" 358 else: 359 print "completely" 360 rmtree(caseDir,ignore_errors=True) 361 362 print 363 print 364 365 if lam!=None: 366 lam.stop() 367 368 print "Total Speedup: ",currentEstimate," ( ",totalSpeedup," / ",totalWeight, " ) Range: [",minSpeedup,",",maxSpeedup,"]" 369 370 print runsOK,"of",len(benchCases),"ran OK" 371 372 resultFile.write("Total Speedup: %g\n" % (currentEstimate)) 373 if minSpeedup and maxSpeedup: 374 resultFile.write("Range: [ %g , %g ]\n" % (minSpeedup,maxSpeedup)) 375 376 resultFile.close()
377