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 3545 2008-08-08T09:22:21.674009Z 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 
 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 print "Machine file ",machineFile,"needed for parallel run" 79 sys.exit(-1) 80 lam=LAMMachine(machineFile,nr=nrCpus) 81 if lam.cpuNr()>nrCpus: 82 print "Wrong number of CPUs: ",lam.cpuNr() 83 sys.exit(-1) 84 85 print "Running parallel on",lam.cpuNr(),"CPUs" 86 87 if config.has_option("General","casesDirectory"): 88 casesDirectory=path.expanduser(config.get("General","casesDirectory")) 89 else: 90 casesDirectory=foamTutorials() 91 92 if not path.exists(casesDirectory): 93 print "Directory",casesDirectory,"needed with the benchmark cases is missing" 94 sys.exit(-1) 95 else: 96 print "Using cases from directory",casesDirectory 97 98 benchCases=[] 99 config.remove_section("General") 100 101 for sec in config.sections(): 102 print "Reading: ",sec 103 skipIt=False 104 skipReason="" 105 if config.has_option(sec,"skip"): 106 skipIt=config.getboolean(sec,"skip") 107 skipReason="Switched off in file" 108 if self.opts.excases!=None and not skipIt: 109 for p in self.opts.excases: 110 if fnmatch(sec,p): 111 skipIt=True 112 skipReason="Switched off by pattern '"+p+"'" 113 if self.opts.cases!=None: 114 for p in self.opts.cases: 115 if fnmatch(sec,p): 116 skipIt=False 117 skipReason="" 118 119 if skipIt: 120 print "Skipping case ..... Reason:"+skipReason 121 continue 122 sol=config.get(sec,"solver") 123 cas=config.get(sec,"case") 124 pre=eval(config.get(sec,"prepare")) 125 preCon=[] 126 if config.has_option(sec,"preControlDict"): 127 preCon=eval(config.get(sec,"preControlDict")) 128 con=eval(config.get(sec,"controlDict")) 129 bas=config.getfloat(sec,"baseline") 130 wei=config.getfloat(sec,"weight") 131 add=[] 132 if config.has_option(sec,"additional"): 133 add=eval(config.get(sec,"additional")) 134 print "Adding: ", add 135 util=[] 136 if config.has_option(sec,"utilities"): 137 util=eval(config.get(sec,"utilities")) 138 print "Utilities: ", util 139 nr=99999 140 if config.has_option(sec,"nr"): 141 nr=eval(config.get(sec,"nr")) 142 sp=None 143 if config.has_option(sec,"blockSplit"): 144 sp=eval(config.get(sec,"blockSplit")) 145 toRm=[] 146 if config.has_option(sec,"filesToRemove"): 147 toRm=eval(config.get(sec,"filesToRemove")) 148 setInit=[] 149 if config.has_option(sec,"setInitial"): 150 setInit=eval(config.get(sec,"setInitial")) 151 152 parallelOK=False 153 if config.has_option(sec,"parallelOK"): 154 parallelOK=config.getboolean(sec,"parallelOK") 155 156 deMet=["metis"] 157 if config.has_option(sec,"decomposition"): 158 deMet=config.get(sec,"decomposition").split() 159 160 if deMet[0]=="metis": 161 pass 162 elif deMet[0]=="simple": 163 if len(deMet)<2: 164 deMet.append(0) 165 else: 166 deMet[1]=int(deMet[1]) 167 else: 168 print "Unimplemented decomposition method",deMet[0],"switching to metis" 169 deMet=["metis"] 170 171 if isParallel==False or parallelOK==True: 172 if path.exists(path.join(casesDirectory,sol,cas)): 173 benchCases.append( (nr,sec,sol,cas,pre,con,preCon,bas,wei,add,util,sp,toRm,setInit,deMet) ) 174 else: 175 print "Skipping",sec,"because directory",path.join(casesDirectory,sol,cas),"could not be found" 176 else: 177 print "Skipping",sec,"because not parallel" 178 179 benchCases.sort() 180 181 parallelString="" 182 if isParallel: 183 parallelString=".cpus="+str(nrCpus) 184 185 resultFile=open("Benchmark."+benchName+"."+uname()[1]+parallelString+".results","w") 186 187 totalSpeedup=0 188 minSpeedup=None 189 maxSpeedup=None 190 totalWeight =0 191 runsOK=0 192 currentEstimate = 1. 193 194 print "\nStart Benching\n" 195 196 csv=CSVCollection("Benchmark."+benchName+"."+uname()[1]+parallelString+".csv") 197 198 # csvHeaders=["description","solver","case","caseDir","base", 199 # "benchmark","machine","arch","cpus","os","version", 200 # "wallclocktime","cputime","cputimeuser","cputimesystem","maxmemory","cpuusage","speedup"] 201 202 for nr,description,solver,case,prepare,control,preControl,base,weight,additional,utilities,split,toRemove,setInit,decomposition in benchCases: 203 # control.append( ("endTime",-2000) ) 204 print "Running Benchmark: ",description 205 print "Solver: ",solver 206 print "Case: ",case 207 caseName=solver+"_"+case+"_"+benchName+"."+uname()[1]+".case" 208 print "Short name: ",caseName 209 caseDir=caseName+".runDir" 210 211 csv["description"]=description 212 csv["solver"]=solver 213 csv["case"]=case 214 csv["caseDir"]=caseDir 215 csv["base"]=base 216 217 csv["benchmark"]=benchName 218 csv["machine"]=uname()[1] 219 csv["arch"]=uname()[4] 220 if lam==None: 221 csv["cpus"]=1 222 else: 223 csv["cpus"]=lam.cpuNr() 224 csv["os"]=uname()[0] 225 csv["version"]=uname()[2] 226 227 workDir=path.realpath(path.curdir) 228 229 orig=SolutionDirectory(path.join(casesDirectory,solver,case), 230 archive=None, 231 paraviewLink=False) 232 for a in additional+utilities: 233 orig.addToClone(a) 234 orig.cloneCase(path.join(workDir,caseDir)) 235 236 if oldApp(): 237 argv=[solver,workDir,caseDir] 238 else: 239 argv=[solver,"-case",path.join(workDir,caseDir)] 240 241 run=BasicRunner(silent=True,argv=argv,logname="BenchRunning",lam=lam) 242 runDir=run.getSolutionDirectory() 243 controlFile=ParameterFile(runDir.controlDict()) 244 245 for name,value in preControl: 246 print "Setting parameter",name,"to",value,"in controlDict" 247 controlFile.replaceParameter(name,value) 248 249 for rm in toRemove: 250 fn=path.join(caseDir,rm) 251 print "Removing file",fn 252 execute("rm -f "+fn) 253 254 for field,bc,val in setInit: 255 print "Setting",field,"on",bc,"to",val 256 SolutionFile(runDir.initialDir(),field).replaceBoundary(bc,val) 257 258 oldDeltaT=controlFile.replaceParameter("deltaT",0) 259 260 for u in utilities: 261 print "Building utility ",u 262 execute("wmake 2>&1 >%s %s" % (path.join(caseDir,"BenchCompile."+u),path.join(caseDir,u))) 263 264 print "Preparing the case: " 265 if lam!=None: 266 prepare=prepare+[("decomposePar","")] 267 if decomposition[0]=="metis": 268 lam.writeMetis(SolutionDirectory(path.join(workDir,caseDir))) 269 elif decomposition[0]=="simple": 270 lam.writeSimple(SolutionDirectory(path.join(workDir,caseDir)),decomposition[1]) 271 272 if split: 273 print "Splitting the mesh:",split 274 bm=BlockMesh(runDir.blockMesh()) 275 bm.refineMesh(split) 276 277 for pre,post in prepare: 278 print "Doing ",pre," ...." 279 post=post.replace("%case%",caseDir) 280 if oldApp(): 281 args=string.split("%s %s %s %s" % (pre,workDir,caseDir,post)) 282 else: 283 args=string.split("%s -case %s %s" % (pre,path.join(workDir,caseDir),post)) 284 util=BasicRunner(silent=True,argv=args,logname="BenchPrepare_"+pre) 285 util.start() 286 287 controlFile.replaceParameter("deltaT",oldDeltaT) 288 289 # control.append(("endTime",-1000)) 290 for name,value in control: 291 print "Setting parameter",name,"to",value,"in controlDict" 292 controlFile.replaceParameter(name,value) 293 294 print "Starting at ",asctime(localtime(time())) 295 print " Baseline is %f, estimated speedup %f -> estimated end at %s " % (base,currentEstimate,asctime(localtime(time()+base/currentEstimate))) 296 print "Running the case ...." 297 run.start() 298 299 speedup=None 300 cpuUsage=0 301 speedupOut=-1 302 303 try: 304 speedup=base/run.run.wallTime() 305 cpuUsage=100.*run.run.cpuTime()/run.run.wallTime() 306 except ZeroDivisionError: 307 print "Division by Zero: ",run.run.wallTime() 308 309 if not run.runOK(): 310 print "\nWARNING!!!!" 311 print "Run had a problem, not using the results. Check the log\n" 312 speedup=None 313 314 if speedup!=None: 315 speedupOut=speedup 316 317 totalSpeedup+=speedup*weight 318 totalWeight +=weight 319 runsOK+=1 320 if maxSpeedup==None: 321 maxSpeedup=speedup 322 elif speedup>maxSpeedup: 323 maxSpeedup=speedup 324 if minSpeedup==None: 325 minSpeedup=speedup 326 elif speedup<minSpeedup: 327 minSpeedup=speedup 328 329 print "Wall clock: ",run.run.wallTime() 330 print "Speedup: ",speedup," (Baseline: ",base,")" 331 print "CPU Time: ",run.run.cpuTime() 332 print "CPU Time User: ",run.run.cpuUserTime() 333 print "CPU Time System: ",run.run.cpuSystemTime() 334 print "Memory: ",run.run.usedMemory() 335 print "CPU Usage: %6.2f%%" % (cpuUsage) 336 337 csv["wallclocktime"]=run.run.wallTime() 338 csv["cputime"]=run.run.cpuTime() 339 csv["cputimeuser"]=run.run.cpuUserTime() 340 csv["cputimesystem"]=run.run.cpuSystemTime() 341 csv["maxmemory"]=run.run.usedMemory() 342 csv["cpuusage"]=cpuUsage 343 if speedup!=None: 344 csv["speedup"]=speedup 345 else: 346 csv["speedup"]="##" 347 348 csv.write() 349 350 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)) 351 352 resultFile.flush() 353 354 if speedup!=None: 355 currentEstimate=totalSpeedup/totalWeight 356 357 if self.opts.removeCases: 358 print "Clearing case", 359 if speedup==None: 360 print "not ... because it failed" 361 else: 362 print "completely" 363 execute("rm -rf "+caseDir) 364 365 print 366 print 367 368 if lam!=None: 369 lam.stop() 370 371 print "Total Speedup: ",currentEstimate," ( ",totalSpeedup," / ",totalWeight, " ) Range: [",minSpeedup,",",maxSpeedup,"]" 372 373 print runsOK,"of",len(benchCases),"ran OK" 374 375 resultFile.write("Total Speedup: %g\n" % (currentEstimate)) 376 if minSpeedup and maxSpeedup: 377 resultFile.write("Range: [ %g , %g ]\n" % (minSpeedup,maxSpeedup)) 378 379 resultFile.close()
380