Author: gnichols Date: 2011-03-08 13:51:50 +0000 (Tue, 08 Mar 2011) New Revision: 795
Modified: trunk/tests/cpuscaling/cpuscaling.py Log: 579498 - RH cert suite cpuscaling test fails Nehalem-EX procs
Modified: trunk/tests/cpuscaling/cpuscaling.py =================================================================== --- trunk/tests/cpuscaling/cpuscaling.py 2011-03-08 13:08:47 UTC (rev 794) +++ trunk/tests/cpuscaling/cpuscaling.py 2011-03-08 13:51:50 UTC (rev 795) @@ -22,6 +22,7 @@ import time import dbus import decimal +import signal
from v7.tags import Constants, DeviceClass, TestTag from v7.test import Test @@ -38,79 +39,83 @@ self.retryTolerance = 5.0 # percent self.sysCPUDirectory = "/sys/devices/system/cpu" self.idaFlag = "ida" - self.idaSpeedupFactor = 8.0 # percent + self.idaSpeedupFactor = 8.0 # percent + self.turboSpeedupTolerance = 5.0 # percent - test expects turbo/ida to increase performance by more than this self.selfTestData = [10.0, 10.0, 10.0, 10.0] # min, max, ondemand, performance self.selfTestStep = 0 self.deviceClass = DeviceClass.processor + self.cpuNumbers = None + self.cpuToPackage = None + self.packageToCpus = None + self.workloads = ["minimum", "maximum", "ondemand", "performance"] + self.workloadTime = dict() # workload run time list indexed by [workload][cpu] + + def setWorkloadTime(self, workload, cpu, time): + if not workload in self.workloadTime: + self.workloadTime[workload] = dict() + if not cpu in self.workloadTime[workload]: + self.workloadTime[workload][cpu] = list() + self.workloadTime[workload][cpu].append(time)
+ def getWorkloadTime(self, workload, cpu): + try: + return self.workloadTime[workload][cpu][-1] # get the last time + except KeyError: + return None + + def getWorkloadTimes(self, workload, cpu): + try: + return self.workloadTime[workload][cpu] # get the whole list of times + except KeyError: + return None + def getWorkloadTimesLength(self, workload): + """ return the max number of entries of any cpu """ + max = 0 + for cpu in self.workloadTime[workload]: + if len(self.workloadTime[workload][cpu]) > max: + max = len(self.workloadTime[workload][cpu]) + return max + + def speedup(self, cpu): + return self.getWorkloadTime("minimum", cpu)/self.getWorkloadTime("maximum", cpu) + + def speedupMargin(self, cpu): + return (abs(self.speedup(cpu)-self.predictedSpeedup)/self.predictedSpeedup)*100 + + def margin(self, cpu, workload): + return (abs(self.getWorkloadTime(workload,cpu)-self.getWorkloadTime("maximum",cpu))/self.getWorkloadTime("maximum",cpu))*100 + def tags(self): return [TestTag.noninteractive, TestTag.certification]
def plan(self, devices): - cpuDevices = list() - canThrottle = False - for device in devices: - # plan a separate test for each cpu - # if any of the cpus appear to support it. - if 'processor' in device.getProperty("info.category"): - cpuDevices.append(device) - if device.getProperty("processor.can_throttle"): - canThrottle = True - - # if no "can_throttle", check the /sys file system + # check the /sys file system to see if scaling looks possible self.getCPUFreqDirectories() - if not canThrottle and self.cpufreqDirectories: - for directory in self.cpufreqDirectories: + cpuScalingSupported = False + if self.cpufreqDirectories: + for directory in self.cpufreqDirectories.values(): availableFreq = os.path.join(directory, "scaling_available_frequencies") if os.path.exists(availableFreq): # if there's more than one frequency, then schedule the tests freqs = open(availableFreq) line = freqs.readline() if line and len(line.split()) > 1: - canThrottle = True + cpuScalingSupported = True freqs.close()
+ # if cpu scaling is supported, just schedule one test. tests = list() - if canThrottle: - for cpuDevice in cpuDevices: - test = self.makeCopy() - test.setDevice(cpuDevice) - cpuNumber = cpuDevice.getProperty("processor.number") - if not cpuNumber: - cpuNumber = "0" - test.setLogicalDeviceName("%s" % cpuNumber) - tests.append(test) + if cpuScalingSupported: + test = self.makeCopy() + tests.append(test)
return tests
def verify(self): - if not self.getLogicalDeviceName(): - while True: - cpuNumber = self.prompt("Please enter the cpu number to be tested:") - try: - int(cpuNumber) - self.setLogicalDeviceName(cpuNumber) - self.parameters.set(Constants.DEVICE, cpuNumber) - break - except ValueError: - print "Please enter just the integer cpu number." - - # do a quick test to see if the cpu number is usable - cpuDirectories = self.getCPUFreqDirectories() - for directory in cpuDirectories: - if ("cpu" + self.getLogicalDeviceName()) in directory: - return True - # otherwise - print "Error: there is no cpufreq directory for cpu" + self.getLogicalDeviceName() - return False - - - - + # disable for now + return True
def getCPUFreqDirectories(self): - self.cpufreqDirectory = "%s/cpu%s/cpufreq" % (self.sysCPUDirectory, self.getLogicalDeviceName()) - if not os.path.exists(self.sysCPUDirectory): print "Error: no file %s" % self.sysCPUDirectory return None @@ -120,18 +125,22 @@ for subdirectory in os.listdir(self.sysCPUDirectory): match = pattern.search(subdirectory) if match and match.group("cpuNumber"): + cpuNumber = match.group("cpuNumber") + if not self.cpuNumbers: + self.cpuNumbers = list() + self.cpuNumbers.append(cpuNumber) cpufreqDirectory = "%s/%s/cpufreq" % (self.sysCPUDirectory, subdirectory) if not os.path.exists(cpufreqDirectory): continue # otherwise if not self.cpufreqDirectories: - self.cpufreqDirectories = list() - self.cpufreqDirectories.append(cpufreqDirectory) + self.cpufreqDirectories = dict() + self.cpufreqDirectories[cpuNumber] = cpufreqDirectory return self.cpufreqDirectories
def checkParameters(self, file): current = None - for cpufreqDirectory in self.cpufreqDirectories: + for cpufreqDirectory in self.cpufreqDirectories.values(): parameters = self.getParameters(cpufreqDirectory, file) if not parameters: print "Error: could not determine cpu parameters from %s/%s" % (cpufreqDirectory, file) @@ -156,11 +165,18 @@ return line.strip().split() return None
- def setParameter(self, switch, setFile, readFile, value): - # try the command for all cpus + def setPackageParameter(self, switch, setFile, readFile, value): + # try the command for all cpus in the package result = True + for cpu in self.packageToCpus[self.currentPackage]: + if not self.setParameter(cpu, switch, setFile, readFile, value): + result = False + return result + + def setParameter(self, cpu, switch, setFile, readFile, value): + result = True try: - command = Command("cpufreq-selector -c %s -%s %s" % (self.getLogicalDeviceName(), switch, value)) + command = Command("cpufreq-selector -c %s -%s %s" % (cpu, switch, value)) command.echo() except V7CommandException, exception: print "Note: command failed: %s" % exception.command @@ -169,7 +185,7 @@ if not result: print "Trying alternate method." try: - command = Command("echo "%s" > %s/%s" % (value, self.cpufreqDirectory, setFile)) + command = Command("echo "%s" > %s/%s" % (value, cpu, setFile)) command.echo() except V7CommandException, exception: print "Error: command failed:" @@ -177,10 +193,10 @@ return False
# verify it has changed - parameterFile = open("%s/%s" % (self.cpufreqDirectory, readFile)) + parameterFile = open("%s/%s" % (self.cpufreqDirectories[cpu], readFile)) line = parameterFile.readline() if not line or line.strip() != value: - print "Error: could not verify that %s/%s was set to %s" % (self.cpufreqDirectory, readFile, value) + print "Error: could not verify that %s/%s was set to %s" % (self.cpufreqDirectories[cpu], readFile, value) if line: print "Actual Value: %s" % line else: @@ -190,20 +206,30 @@ return True
def setFrequency(self, frequency): - return self.setParameter("f", "scaling_setspeed", "scaling_cur_freq", frequency) + return self.setPackageParameter("f", "scaling_setspeed", "scaling_cur_freq", frequency)
def setGovernor(self, governor): - return self.setParameter("g", "scaling_governor", "scaling_governor", governor) + return self.setPackageParameter("g", "scaling_governor", "scaling_governor", governor)
- - def getParameter(self, parameter): + def getPackageParameter(self, parameter): + packageParameterValue = None + for cpu in self.packageToCpus[self.currentPackage]: + value = self.getParameter(cpu, parameter) + if value and not packageParameterValue: + packageParameterValue = value + elif value != packageParameterValue: + print "Error: cpu%s in package %s has the value %s which differs from other cpus in the package" % (cpu, self.currentPackage, value) + return None + return packageParameterValue + + def getParameter(self, cpu, parameter): value = None - parameterFilePath = "%s/%s" % (self.cpufreqDirectory, parameter) + parameterFilePath = "%s/%s" % (self.cpufreqDirectories[cpu], parameter) try: parameterFile = open(parameterFilePath) line = parameterFile.readline() if not line: - print "Error: failed to get %s for %s" % (parameter, cpufreqDirectory) + print "Error: failed to get %s for %s" % (parameter, self.cpufreqDirectories[cpu]) return None value = line.strip() return value @@ -215,7 +241,7 @@
def getParameterList(self, parameter): values = list() - for cpufreqDirectory in self.cpufreqDirectories: + for cpufreqDirectory in self.cpufreqDirectories.values(): parameterFile = open("%s/%s" % (cpufreqDirectory, parameter)) line = parameterFile.readline() if not line: @@ -225,31 +251,23 @@
return values
- def _runLoadTest(self): + def runLoadTest(self, cpu=None): + """ run package load test, cpu default None means for all cpus """ print "Running CPU load test..." - sys.stdout.flush() - try: - Command("taskset -pc %s %s" % (self.getLogicalDeviceName(), os.getpid())).echo() - except V7CommandException, exception: - print "Error: could not set task affinity" - print exception - return None
runTime = None tries = 0 while tries < self.retryLimit: sys.stdout.flush() - (start_utime, start_stime, start_cutime, start_cstime, start_elapsed_time) = os.times() - # os.system("echo "scale=2^12; 4*a(1)" | bc -l > /dev/null") - self.pi() - (stop_utime, stop_stime, stop_cutime, stop_cstime, stop_elapsed_time) = os.times() + averageProcessTime = self.__runSubprocessLoadTest(cpu) + print "average worker process time: %.2f seconds" % averageProcessTime if not runTime: - runTime = stop_elapsed_time - start_elapsed_time + runTime = averageProcessTime else: - thisTime = stop_elapsed_time - start_elapsed_time + thisTime = averageProcessTime # print "comparing %.2f" % (abs(thisTime-runTime)/runTime) if (abs(thisTime-runTime)/runTime)*100 < self.retryTolerance: - return runTime + return thisTime else: runTime = thisTime tries += 1 @@ -258,39 +276,59 @@ print "Error: could not repeat load test times within %.1f%%" % self.retryTolerance return None
- def runLoadTest(self): - result = self._runLoadTest() - print "CPU Load finished." - sys.stdout.flush() - if self.getMode() == Constants.self: - print "Warning: in self-test mode, returning face data" - result = self.selfTestData[self.selfTestStep] - self.selfTestStep = self.selfTestStep + 1 - return result + def __runSubprocessLoadTest(self, cpu=None): + print "Running load test for package " + self.currentPackage + self.loadProcesses = dict()
- - def pi(self): - decimal.getcontext().prec = 500 - s = decimal.Decimal(1) - h = decimal.Decimal(3).sqrt()/2 - n = 6 - for i in range(170): - A = n*h*s/2 # A ... area of polygon - s2 = ((1-h)**2+s**2/4) - s = s2.sqrt() - h = (1-s2/4).sqrt() - n = 2*n - # print i,":",A - return True + # if cpu is set, just load that one + if cpu: + loadProcess = LoadProcess(self, cpu) + loadProcess.start() + self.loadProcesses[cpu] = loadProcess + else: # load all cpus in the package + for cpu in self.packageToCpus[self.currentPackage]: + loadProcess = LoadProcess(self, cpu) + loadProcess.start() + self.loadProcesses[cpu] = loadProcess + + print "waiting for load processes..." + totalProcessTime = 0 + numberOfProcesses = len(self.loadProcesses) + while len(self.loadProcesses) > 0 : + for (cpu, process) in self.loadProcesses.items(): + if process.isDone(): + if process.returnCode is not 0: + print "Error: load process terminated with return code " + process.returnCode + return None + runTime = process.getRunTime() + if not runTime: + print "Error: could not find process run time" + return None + # otherwise - collect info + print "process for cpu %s is done in %.2f seconds" % (cpu, runTime) + self.setWorkloadTime(self.currentWorkload, cpu, runTime) + totalProcessTime += runTime + del self.loadProcesses[cpu] + + time.sleep(1) # poll once per second + print "processes complete" + return totalProcessTime/numberOfProcesses
+ def done(self, cpu): + print "process for cpu %s is done. (caught SIGCHLD)" % cpu + try: + del self.loadProcesses[cpu] + except KeyError: + print "Error: no cpu %s in load processes" % cpu + def verifyMinimumFrequency(self): waitTime = 5 sys.stdout.write("Waiting %d seconds..." % waitTime) sys.stdout.flush() time.sleep(waitTime) sys.stdout.write(" done.\n") - minimumFrequency = self.getParameter("scaling_min_freq") - currentFrequency = self.getParameter("scaling_cur_freq") + minimumFrequency = self.getPackageParameter("scaling_min_freq") + currentFrequency = self.getPackageParameter("scaling_cur_freq") if not minimumFrequency or not currentFrequency or (minimumFrequency != currentFrequency): return False
@@ -301,7 +339,6 @@ print "" print "System Capabilites:" print "-------------------------------------------------" - print "Testing cpu %s" % self.getLogicalDeviceName()
# 1. Determine if the cpu's support scaling using presense or lack there of ~/cpufreq in sysfs
@@ -309,8 +346,35 @@ return False if len (self.cpufreqDirectories) > 1: print "System has %u cpus"% len(self.cpufreqDirectories) - - # 2. Check ~/cpu[*]/scaling_available_freq files to ensure that all cpu's scale the same ammount; if not bail + + # 1.5 get core/package topology + if self.cpuNumbers: + for cpuNumber in self.cpuNumbers: + sys.stdout.flush() + parameters = self.getParameters(os.path.join(self.sysCPUDirectory, ("cpu" + cpuNumber), "topology"), "physical_package_id") + if parameters and len(parameters) == 1: + packageNumber = parameters[0] + if not self.cpuToPackage: + self.cpuToPackage = dict() + self.cpuToPackage[cpuNumber] = packageNumber + if not self.packageToCpus: + self.packageToCpus = dict() + if not packageNumber in self.packageToCpus: + self.packageToCpus[packageNumber] = list() + if cpuNumber not in self.packageToCpus[packageNumber]: + self.packageToCpus[packageNumber].append(cpuNumber) + else: + print "Warning: could not determine cpu topology: no package ID for cpu " + cpuNumber + # print them out + for package in self.packageToCpus.keys(): + sys.stdout.write("package %s has cpus: " % package) + sys.stdout.write(", ".join(self.packageToCpus[package])) + print "" + print "" + + # 2. Check ~/cpu[*]/scaling_available_freq files to ensure that all cpu's scale the same amount; if not bail + print "Checking freguencies" + sys.stdout.flush() freqFileName = "scaling_available_frequencies" frequencies = self.checkParameters(freqFileName) if not frequencies: @@ -351,6 +415,8 @@ print "Error: could not determine current governor settings" return False
+ + self.getCPUFlags() sys.stdout.flush()
@@ -366,6 +432,16 @@ print "Warning: could not read CPU flags" print exception
+ def turboBoostSupported(self): + # if "ida" turbo thing, increase the expectation by 8% + if self.cpuFlags and self.idaFlag in self.cpuFlags: + return True + #otherwise + return False + + # print "Note: found %s flag, increasing expected speedup by %.1f%%" % (self.idaFlag, self.idaSpeedupFactor) + # self.predictedSpeedup = self.predictedSpeedup*(1.0/(1.0-(self.idaSpeedupFactor/100.0))) +
def runUserSpaceTests(self): print "" @@ -375,8 +451,11 @@ # 5. Set the govr.(*) to "userspace" for each cpu via a command similar to: # 6. Verify the govr. setting took by checking ~/scaling_governor self.differenceSpeedUp = None - self.minimumFrequencyTestTime = None - self.maximumFrequencyTestTime = None + # calculate predicted (theoretical) speed up based on scaling frequencies + maximumFrequency = self.getPackageParameter("scaling_max_freq") + minimumFrequency = self.getPackageParameter("scaling_min_freq") + self.predictedSpeedup = string.atof(maximumFrequency)/string.atof(minimumFrequency) + success = True governor = "userspace" if governor in self.governors: @@ -386,15 +465,18 @@
# 7. Set the the cpu speed to it's lowest value frequency = self.frequencies[0] - currentFrequency = self.getParameter("scaling_cur_freq") - print "Changing cpu frequency from %u to %u MHz" % (int(currentFrequency)/1000, (frequency/1000)) + currentFrequency = self.getPackageParameter("scaling_cur_freq") + if currentFrequency: + print "Changing cpu frequency from %u to %u MHz" % (int(currentFrequency)/1000, (frequency/1000)) + else: + print "Setting cpu frequency to %u MHz" % (frequency/1000) if not self.setFrequency("%u" % frequency): success = False + self.currentWorkload = "minimum" sys.stdout.flush()
# 8. Verify the speed is set to the lowest value by comparing ~/scaling_min_freq to ~/scaling_cur_freq - minimumFrequency = self.getParameter("scaling_min_freq") - currentFrequency = self.getParameter("scaling_cur_freq") + currentFrequency = self.getPackageParameter("scaling_cur_freq") if not minimumFrequency or not currentFrequency or (minimumFrequency != currentFrequency): print "Error: Could not verify that cpu frequency is set to the minimum value of %s" % minimumFrequency success = False @@ -405,17 +487,17 @@ self.minimumFrequencyTestTime = self.runLoadTest() if not self.minimumFrequencyTestTime: return False - print "Minumum frequency load test time: %.2f" % self.minimumFrequencyTestTime + print "Minumum frequency average load test time: %.2f" % self.minimumFrequencyTestTime
# 11. Set the cpu speed to it's highest value as above. frequency = self.frequencies[-1] - currentFrequency = self.getParameter("scaling_cur_freq") + currentFrequency = self.getPackageParameter("scaling_cur_freq") print "Changing cpu frequency from %u to %u MHz" % (int(currentFrequency)/1000, (frequency/1000)) if not self.setFrequency("%u" % frequency): success = False + self.currentWorkload = "maximum"
- maximumFrequency = self.getParameter("scaling_max_freq") - currentFrequency = self.getParameter("scaling_cur_freq") + currentFrequency = self.getPackageParameter("scaling_cur_freq") if not maximumFrequency or not currentFrequency or (maximumFrequency != currentFrequency): print "Error: Could not verify that cpu frequency is set to the maximum value of %s" % maximumFrequency success = False @@ -424,26 +506,23 @@ self.maximumFrequencyTestTime = self.runLoadTest() if not self.maximumFrequencyTestTime: return False - print "Maximum frequency load test time: %.2f" % self.maximumFrequencyTestTime + print "Maximum frequency average load test time: %.2f" % self.maximumFrequencyTestTime
# 13. Verify MHz increase is comparable to time % decrease( eg. slow MHz/fast MHz ~= fast time/slow time; # again with self.speedUpTolerance margin) - predictedSpeedup = string.atof(maximumFrequency)/string.atof(minimumFrequency) +
- # if "ida" turbo thing, increase the expectation by 8% - if self.cpuFlags and self.idaFlag in self.cpuFlags: - print "Note: found %s flag, increasing expected speedup by %.1f%%" % (self.idaFlag, self.idaSpeedupFactor) - predictedSpeedup = predictedSpeedup*(1.0/(1.0-(self.idaSpeedupFactor/100.0))) - - measuredSpeedup = self.minimumFrequencyTestTime/self.maximumFrequencyTestTime - print "" - print "CPU Frequency Speed Up: %.2f" % predictedSpeedup - print "Measured Speed Up: %.2f" % measuredSpeedup - self.differenceSpeedUp = (abs(measuredSpeedup-predictedSpeedup)/predictedSpeedup)*100 - print "Percentage Difference %.1f%%" % self.differenceSpeedUp - if self.differenceSpeedUp > self.speedUpTolerance: - print "Error: measured speedup vs expected speedup is %.1f%% and is not within %.1f%% margin. " % (self.differenceSpeedUp, self.speedUpTolerance) - success = False + # for each cpu in the package + for cpu in self.packageToCpus[self.currentPackage]: + measuredSpeedup = self.speedup(cpu) + print "" + print "CPU Frequency Speed Up: %.2f" % self.predictedSpeedup + print "CPU %s Measured Speed Up: %.2f" % (cpu, measuredSpeedup) + self.differenceSpeedUp = self.speedupMargin(cpu) + print "Percentage Difference %.1f%%" % self.differenceSpeedUp + if self.differenceSpeedUp > self.speedUpTolerance: + print "Error: measured speedup vs expected speedup is %.1f%% and is not within %.1f%% margin. " % (self.differenceSpeedUp, self.speedUpTolerance) + success = False else: print "Note: %s governor not supported" % governor
@@ -463,6 +542,7 @@ print "Setting governor to %s" % governor if not self.setGovernor(governor): success = False + self.currentWorkload = "ondemand"
# 16. Wait a fixed period of time, then verify current speed is the slowest in as before if not self.verifyMinimumFrequency(): @@ -476,15 +556,17 @@ print "On Demand load test time: %.2f" % self.onDemandTestTime
# 18. Compare the timing to the max results from earlier, again time should be within self.speedUpTolerance - if self.maximumFrequencyTestTime: - self.differenceOnDemandVsMaximum = (abs(self.onDemandTestTime-self.maximumFrequencyTestTime)/self.maximumFrequencyTestTime)*100 - print "Percentage Difference vs. maximum frequency: %.1f%%" % self.differenceOnDemandVsMaximum - if self.differenceOnDemandVsMaximum > self.speedUpTolerance: - print "Error: on demand performance vs maximum of %.1f%% is not within %.1f%% margin" % (self.differenceOnDemandVsMaximum, self.speedUpTolerance) + # for each cpu in the package + for cpu in self.packageToCpus[self.currentPackage]: + if self.getWorkloadTime("maximum", cpu): + self.differenceOnDemandVsMaximum = self.margin(cpu, "ondemand") + print "Percentage Difference vs. maximum frequency: %.1f%%" % self.differenceOnDemandVsMaximum + if self.differenceOnDemandVsMaximum > self.speedUpTolerance: + print "Error: on demand performance vs maximum of %.1f%% is not within %.1f%% margin" % (self.differenceOnDemandVsMaximum, self.speedUpTolerance) + success = False + else: + print "No maximum frequency test data to compare" success = False - else: - print "No maximum frequency test data to compare" - success = False
# 19. Verify the current speed has returned to the lowest speed as before if not self.verifyMinimumFrequency(): @@ -508,10 +590,11 @@ print "Setting governor to %s" % governor if not self.setGovernor(governor): success = False + self.currentWorkload = "performance"
# 21. Verify the current speed is the same as scaling_max_freq - maximumFrequency = self.getParameter("scaling_max_freq") - currentFrequency = self.getParameter("scaling_cur_freq") + maximumFrequency = self.getPackageParameter("scaling_max_freq") + currentFrequency = self.getPackageParameter("scaling_cur_freq") if not maximumFrequency or not currentFrequency or (maximumFrequency != currentFrequency): print "Error: Current cpu frequency of %.2f is not set to the maximum value of %.2f" % (currentFrequency, maximumFrequency) return False @@ -524,45 +607,162 @@ print "Performance load test time: %.2f" % self.performanceTestTime
# 23. Compare the timing to the max results for a self.speedUpTolerance delta - self.differencePerformanceVsMaximum = (abs(self.performanceTestTime-self.maximumFrequencyTestTime)/self.maximumFrequencyTestTime)*100 - print "Percentage Difference vs. maximum frequency: %.1f%%" % self.differencePerformanceVsMaximum - if self.differencePerformanceVsMaximum > self.speedUpTolerance: - print "Error: performance setting vs maximum of %.1f%% is not within %.1f%% margin" % (self.differencePerformanceVsMaximum, self.speedUpTolerance) - success = False + for cpu in self.packageToCpus[self.currentPackage]: + self.differencePerformanceVsMaximum = self.margin(cpu, "performance") + print "Percentage Difference vs. maximum frequency: %.1f%%" % self.differencePerformanceVsMaximum + if self.differencePerformanceVsMaximum > self.speedUpTolerance: + print "Error: performance setting vs maximum of %.1f%% is not within %.1f%% margin" % (self.differencePerformanceVsMaximum, self.speedUpTolerance) + success = False
else: print "Note: %s governor not supported" % governor
return success
+ def runTurboBoostTest(self): + """ test one cpu in the package while others are idle, and verify that its speedup is greater than when all + cpus in the package are loaded """ + print "" + print "Turbo Boost Test:" + print "-------------------------------------------------" + self.differenceTurboVsMaximum = None + # 30. Set and verify the govr. to "performance" + governor = "ondemand" + success = True + if governor in self.governors: + print "Setting governor to %s" % governor + if not self.setGovernor(governor): + success = False + self.currentWorkload = "turbo" + + # 32 Pick a cpu other than cpu0 to load + turboCpu = self.getTurboCpu() + print "Using cpu %s to test Turbo/IDA performance" % turboCpu + + + # 33. Repeat workload test, loading a single cpu + self.turboTestTime = self.runLoadTest(cpu=turboCpu) + if not self.turboTestTime: + return False + # otherwise + print "Turbo/IDA load test time: %.2f" % self.turboTestTime + + # 23. Compare the timing to the max results for a self.speedUpTolerance delta + self.differenceTurboVsMaximum = self.margin(turboCpu, "turbo") + print "Percentage Difference vs. maximum frequency: %.1f%%" % self.differenceTurboVsMaximum + if self.differenceTurboVsMaximum < self.turboSpeedupTolerance: + print "Error: turbo/IDA setting vs maximum of %.1f%% is not within %.1f%% margin" % (self.differenceTurboVsMaximum, self.turboSpeedupTolerance) + success = False + + else: + print "Error: %s governor not supported" % governor + success = False + + return success + + def getTurboCpu(self): + # 32 Pick a cpu other than cpu0 to load + for turboCpu in self.packageToCpus[self.currentPackage]: + if turboCpu != "0": + break + return turboCpu + def restoreGovernors(self): print "Restoring original governor to %s" % (self.originalGovernors[0]) self.setGovernor(self.originalGovernors[0])
+ def runSummary(self): + for package in self.packageToCpus.keys(): + self.printSummary(package) + + for package in self.packageToCpus.keys(): + self.printWorkloadTimeSummary(package) + + return True +
- def printSummary(self): + def printSummary(self, package): + """ tables: row title is 13 characters, each cpu cell is 9 characters """ print "" - print "Summary:" - print "-------------------------------------------------" - print "Load Test Times:" - if self.minimumFrequencyTestTime: - print " Minimum: %.2f" % self.minimumFrequencyTestTime - if self.maximumFrequencyTestTime: - print " Maximum: %.2f" % self.maximumFrequencyTestTime - if self.onDemandTestTime: - print " On Demand: %.2f" % self.onDemandTestTime - if self.performanceTestTime: - print " Performance: %.2f" % self.performanceTestTime - - print "Margins:" - if self.differenceSpeedUp: - print " Speed Up: %.1f%%" % self.differenceSpeedUp - if self.differenceOnDemandVsMaximum: - print " On Demand: %.1f%%" % self.differenceOnDemandVsMaximum - if self.differencePerformanceVsMaximum: - print " Performance: %.1f%%" % self.differencePerformanceVsMaximum - + print "Summary for Package %s:" % package + self.__printBorder(package) + sys.stdout.write("Workload ") + for cpu in self.packageToCpus[package]: + sys.stdout.write(" cpu %-3s " % cpu) print "" + self.__printBorder(package) + for workload in self.workloads: + if workload in self.workloadTime: + sys.stdout.write("%-13s" % workload) + for cpu in self.packageToCpus[package]: + sys.stdout.write("%9.2f" % self.getWorkloadTime(workload, cpu)) + print "" + print "\n" + + sys.stdout.write("Speedup ") + for cpu in self.packageToCpus[package]: + sys.stdout.write(" cpu %-3s " % cpu) + print "" + self.__printBorder(package) + sys.stdout.write("expected ") + for cpu in self.packageToCpus[package]: + sys.stdout.write("%9.2f" % self.predictedSpeedup) + print "" + sys.stdout.write("actual ") + for cpu in self.packageToCpus[package]: + sys.stdout.write("%9.2f" % self.speedup(cpu)) + print "" + sys.stdout.write("margin ") + for cpu in self.packageToCpus[package]: + sys.stdout.write("%8.2f%%" % self.speedupMargin(cpu)) + print "" + for workload in ["ondemand", "performance"]: + if workload in self.workloadTime.keys(): # iterate over logged workloads + sys.stdout.write("%-13s" % workload) + for cpu in self.packageToCpus[package]: + sys.stdout.write("%8.2f%%" % self.margin(cpu, workload)) + print "" + if "turbo" in self.workloadTime: + sys.stdout.write("%-13s" % "turbo") + turboCpu = self.getTurboCpu() + for cpu in self.packageToCpus[package]: + if cpu == turboCpu: + sys.stdout.write("%8.2f%%" % self.margin(cpu, "turbo")) + else: + sys.stdout.write(" - ") + print "" + print "\n" + + def printWorkloadTimeSummary(self, package): + sys.stdout.write("Workload run times for package %s:\n" % package) + sys.stdout.write("-------------------\n") + workloads = self.workloads + workloads.append("turbo") + for workload in workloads: + if workload in self.workloadTime: + sys.stdout.write("%-13s" % workload) + run = 1 + for run in range(1, self.getWorkloadTimesLength(workload)+1): + sys.stdout.write(" %7u " % run) + run += 1 + sys.stdout.write("\n") + for cpu in self.packageToCpus[package]: + if self.getWorkloadTimes(workload, cpu): + sys.stdout.write(" cpu %3s: " % cpu) + for time in self.getWorkloadTimes(workload, cpu): + if time: + sys.stdout.write("%9.2f" % time) + else: + sys.stdout.write(" - ") + print "" + print "" + print "\n" + + def __printBorder(self, package): + sys.stdout.write("-------------") # 13 for row title + for cpu in self.packageToCpus[package]: + sys.stdout.write(" --------") # 9 for cpu cell ( 1 space, 8 -) + sys.stdout.write("\n")
def run(self): PASSED = 0 @@ -570,28 +770,121 @@
if not self.runSubTest(self.getSystemCapabilities, "Capabilities"): return FAILED - - self.waitForLull()
- result = PASSED + for package in self.packageToCpus.keys(): + + print "Testing CPU Package " + package + self.currentPackage = package + + self.waitForLull() + + result = PASSED + + if not self.runSubTest(self.runUserSpaceTests, "User Space, package %s" % package): + result = FAILED + + + if not self.runSubTest(self.runOnDemandTests, "On Demand, package %s" % package): + result = FAILED + + if not self.runSubTest(self.runPerformanceTests, "Performance, package %s" % package): + result = FAILED + + if self.turboBoostSupported(): + if not self.runSubTest(self.runTurboBoostTest, "Turbo Boost/IDA, package %s" % package): + result = FAILED +
- if not self.runSubTest(self.runUserSpaceTests, "User Space"): - result = FAILED + self.restoreGovernors() + + if not self.runSubTest(self.runSummary, "Summary"): + result = FAILED + +
- if not self.runSubTest(self.runOnDemandTests, "On Demand"): - result = FAILED - - if not self.runSubTest(self.runPerformanceTests, "Performance"): - result = FAILED
- self.printSummary() + return result + +class LoadProcess: + def __init__(self, owner, cpu): + self.owner = owner + self.cpu = cpu + self.workProcess = None + self.returnCode = None + self.start_elapsed_time = None + self.runTime = None + # signal.signal(signal.SIGCHLD, self.sigChldHandler) + + def start(self): + try: + print "starting process for cpu %s" % self.cpu + self.workProcess = Command("./cpuscaling.py work %s" % self.cpu) + self.workProcess.start() + taskset = Command("taskset -pc %s %s" % (self.cpu, self.workProcess.getPID())) + if self.owner.debug != Constants.off: + taskset.echo() + else: + taskset.run() + except V7CommandException, exception: + print "Error: could not start load process" + print exception + print exception.command.printErrors() + return False + return True + + def getRunTime(self): + return self.runTime + + def sigChldHandler(self, signalNumber, stackFrame): + print "Got signal %d" % signalNumber + self.__stopTimer() + self.owner.done(self.cpu)
- self.restoreGovernors() + def isDone(self): + if self.workProcess and self.workProcess.poll() is not None: + self.returnCode = self.workProcess.poll() + while True: + line = self.workProcess.readline() + if line: + try: + self.runTime = float(line) + return True + except ValueError: + pass # keep trying + else: + print "Error: could not determine process run time" + break + return True + # otherwise + return False + + def getReturnCode(self): + return self.returnCode + +def pi(): + decimal.getcontext().prec = 500 + s = decimal.Decimal(1) + h = decimal.Decimal(3).sqrt()/2 + n = 6 + for i in range(170): + A = n*h*s/2 # A ... area of polygon + s2 = ((1-h)**2+s**2/4) + s = s2.sqrt() + h = (1-s2/4).sqrt() + n = 2*n + # print i,":",A + return True
- return result - - if __name__ == "__main__": + + if "work" in sys.argv: + (start_utime, start_stime, start_cutime, start_cstime, start_elapsed_time) = os.times() + pi() + (stop_utime, stop_stime, stop_cutime, stop_cstime, stop_elapsed_time) = os.times() + runTime = stop_elapsed_time - start_elapsed_time + print runTime + sys.exit(0) + test = CPUScalingTest() returnValue = test.do(sys.argv) sys.exit(returnValue)
v7-commits@lists.stg.fedorahosted.org