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

Source Code for Module PyFoam.Applications.Benchmark

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