1# ######################################################################## 2# Copyright 2013 Advanced Micro Devices, Inc. 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15# ######################################################################## 16 17import sys 18import argparse 19import subprocess 20import itertools 21import re#gex 22import os 23import math 24from threading import Timer, Thread 25import thread, time 26from platform import system 27import numpy as np 28 29from datetime import datetime 30 31import errorHandler 32from fftPerformanceTesting import * 33from performanceUtility import timeout, log, generate235Radices 34 35IAM = 'FFT' 36TIMOUT_VAL = 900 #In seconds 37 38devicevalues = ['g', 'c'] 39layoutvalues = ['cp', 'ci'] 40placevalues = ['in', 'out'] 41precisionvalues = ['single', 'double'] 42libraryvalues = ['clFFT','cuFFT'] 43pow10 = '1-9,10-90:10,100-900:100,1000-9000:1000,10000-90000:10000,100000-900000:100000,1000000-9000000:1000000' 44 45parser = argparse.ArgumentParser(description='Measure performance of the clFFT library') 46parser.add_argument('--device', 47 dest='device', default='g', 48 help='device(s) to run on; may be a comma-delimited list. choices are ' + str(devicevalues) + '. (default gpu)') 49parser.add_argument('-b', '--batchsize', 50 dest='batchSize', default='1', 51 help='number of FFTs to perform with one invocation of the client. the special value \'adapt\' may be used to adjust the batch size on a per-transform basis to the maximum problem size possible on the device. (default 1)'.format(pow10)) 52parser.add_argument('-a', '--adaptivemax', 53 dest='constProbSize', default='-1', 54 help='Max problem size that you want to maintain across the invocations of client with different lengths. This is adaptive and adjusts itself automtically.'.format(pow10)) 55parser.add_argument('-x', '--lengthx', 56 dest='lengthx', default='1', 57 help='length(s) of x to test; must be factors of 1, 2, 3, or 5 with clFFT; may be a range or a comma-delimited list. e.g., 16-128 or 1200 or 16,2048-32768 (default 1)') 58parser.add_argument('-y', '--lengthy', 59 dest='lengthy', default='1', 60 help='length(s) of y to test; must be factors of 1, 2, 3, or 5 with clFFT; may be a range or a comma-delimited list. e.g., 16-128 or 1200 or 16,32768 (default 1)') 61parser.add_argument('-z', '--lengthz', 62 dest='lengthz', default='1', 63 help='length(s) of z to test; must be factors of 1, 2, 3, or 5 with clFFT; may be a range or a comma-delimited list. e.g., 16-128 or 1200 or 16,32768 (default 1)') 64parser.add_argument('-reps', 65 dest='reps', default='10', 66 help='Number of repetitions (default 10)') 67parser.add_argument('-prime_factor', '--prime_factor', 68 dest='prime_factor', default='2', 69 help='only test the prime factors within the specified range of lengthx/y/z. Select from 2,3,5, and 7. Example: -prime_factor 2,3') 70parser.add_argument('-test_count', '--test_count', 71 dest='test_count', default='100', 72 help='Number of tests to perform') 73parser.add_argument('--problemsize', 74 dest='problemsize', default=None) 75# help='additional problems of a set size. may be used in addition to lengthx/y/z. each indicated problem size will be added to the list of FFTs to perform. should be entered in AxBxC:D format. A, B, and C indicate the sizes of the X, Y, and Z dimensions (respectively). D is the batch size. All values except the length of X are optional. may enter multiple in a comma-delimited list. e.g., 2x2x2:32768 or 256x256:100,512x512:256') 76parser.add_argument('-i', '--inputlayout', 77 dest='inputlayout', default='1', 78 help=' 1. interleaved (default) 2. planar 3. hermitian interleaved 4. hermitian planar 5. real' ) 79parser.add_argument('-o', '--outputlayout', 80 dest='outputlayout', default='1', 81 help=' 1. interleaved (default) 2. planar 3. hermitian interleaved 4. hermitian planar 5. real' ) 82parser.add_argument('--placeness', 83 dest='placeness', default='in', 84 help='Choices are ' + str(placevalues) + '. in = in place, out = out of place (default in)') 85parser.add_argument('-r', '--precision', 86 dest='precision', default='single', 87 help='Choices are ' + str(precisionvalues) + '. (default single)') 88parser.add_argument('--library', 89 dest='library', default='clFFT', choices=libraryvalues, 90 help='indicates the library to use for testing on this run') 91parser.add_argument('--label', 92 dest='label', default=None, 93 help='a label to be associated with all transforms performed in this run. if LABEL includes any spaces, it must be in \"double quotes\". note that the label is not saved to an .ini file. e.g., --label cayman may indicate that a test was performed on a cayman card or --label \"Windows 32\" may indicate that the test was performed on Windows 32') 94#parser.add_argument('--createini', 95# dest='createIniFilename', default=None, 96# help='create an .ini file with the given name that saves the other parameters given at the command line, then quit. e.g., \'measureperformance.py -x 2048 --createini my_favorite_setup.ini\' will create an .ini file that will save the configuration for a 2048-datapoint 1D FFT.') 97parser.add_argument('--ini', 98 dest='iniFilename', default=None, 99 help='use the parameters in the named .ini file instead of the command line parameters.') 100parser.add_argument('--tablefile', 101 dest='tableOutputFilename', default=None, 102 help='save the results to a plaintext table with the file name indicated. this can be used with plotPerformance.py to generate graphs of the data (default: table prints to screen)') 103parser.add_argument('--prefix', 104 dest='prefix', default='./', 105 help='Path where the library client is located (default current directory)') 106 107args = parser.parse_args() 108 109label = str(args.label) 110 111subprocess.call('mkdir perfLog', shell = True) 112logfile = os.path.join('perfLog', (label+'-'+'fftMeasurePerfLog.txt')) 113 114def printLog(txt): 115 print txt 116 log(logfile, txt) 117 118printLog("=========================MEASURE PERFORMANCE START===========================") 119printLog("Process id of Measure Performance:"+str(os.getpid())) 120 121currCommandProcess = None 122 123 124printLog('Executing measure performance for label: '+str(label)) 125 126 127#This function is defunct now 128@timeout(1, "fileName") # timeout is 5 minutes, 5*60 = 300 secs 129def checkTimeOutPut2(args): 130 global currCommandProcess 131 #ret = subprocess.check_output(args, stderr=subprocess.STDOUT) 132 #return ret 133 currCommandProcess = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 134 printLog("Curr Command Process id = "+str(currCommandProcess.pid)) 135 ret = currCommandProcess.communicate() 136 if(ret[0] == None or ret[0] == ''): 137 errCode = currCommandProcess.poll() 138 raise subprocess.CalledProcessError(errCode, args, output=ret[1]) 139 return ret[0] 140 141 142#Spawns a separate thread to execute the library command and wait for that thread to complete 143#This wait is of 900 seconds (15 minutes). If still the thread is alive then we kill the thread 144def checkTimeOutPut(args): 145 t = None 146 global currCommandProcess 147 global stde 148 global stdo 149 stde = None 150 stdo = None 151 def executeCommand(): 152 global currCommandProcess 153 global stdo 154 global stde 155 try: 156 stdo, stde = currCommandProcess.communicate() 157 printLog('stdout:\n'+str(stdo)) 158 printLog('stderr:\n'+str(stde)) 159 except: 160 printLog("ERROR: UNKNOWN Exception - +checkWinTimeOutPut()::executeCommand()") 161 162 currCommandProcess = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE,shell=True) 163 thread = Thread(target=executeCommand) 164 thread.start() 165 thread.join(TIMOUT_VAL) #wait for the thread to complete 166 if thread.is_alive(): 167 printLog('ERROR: Killing the process - terminating thread because it is taking too much of time to execute') 168 currCommandProcess.kill() 169 printLog('ERROR: Timed out exception') 170 raise errorHandler.ApplicationException(__file__, errorHandler.TIME_OUT) 171 if stdo == "" or stdo==None: 172 errCode = currCommandProcess.poll() 173 printLog('ERROR: @@@@@Raising Called processor exception') 174 raise subprocess.CalledProcessError(errCode, args, output=stde) 175 return stdo 176 177 178 179 180 181# don't try to create and use an .ini file at the same time (it will open a portal through which demons will emerge) 182#if args.iniFilename and args.createIniFilename: 183# printLog('ERROR: --ini and --createini are mutually exclusive. Please choose only one.') 184# quit() 185 186#read in .ini parameters if --ini is used 187#if args.iniFilename != None: 188# if not os.path.isfile(args.iniFilename): 189# printLog("No file with the name \'{}\' exists. Please indicate another filename.".format(args.iniFilename)) 190# quit() 191# 192# ini = open(args.iniFilename, 'r') 193# iniContents = ini.read() 194# iniContents = iniContents.split(';') 195# for i in range(0,len(iniContents)): 196# line = iniContents.pop() 197# line = line.partition(' ') 198# parameter = line[0] 199# value = line[2] 200# value = value.replace('\'','').replace('[','').replace(']','').replace(' ','') 201# print"value= ",value 202# 203# if parameter == 'batchSize': 204# args.batchSize = value 205# elif parameter == 'constProbSize': 206# args.constProbSize = value 207# elif parameter == 'lengthx': 208# args.lengthx = value 209# elif parameter == 'reps': 210# args.reps = value 211# elif parameter == 'prime_factor': 212# args.prime_factor = value 213# elif parameter == 'test_count': 214# args.test_count = value 215# elif parameter == 'lengthy': 216# args.lengthy = value 217# elif parameter == 'lengthz': 218# args.lengthz = value 219# elif parameter == 'problemsize': 220# args.problemsize = value 221# elif parameter == 'device': 222# args.device = value 223# elif parameter == 'inputlayout': 224# args.inputlayout = value 225# elif parameter == 'outputlayout': 226# args.outputlayout = value 227# elif parameter == 'placeness': 228# args.placeness = value 229# elif parameter == 'precision': 230# args.precision = value 231# else: 232# printLog('{} corrupted. Please re-create a .ini file with the --createini flag.'.format(args.iniFilename)) 233# #quit() 234 235#create ini file if requested 236#if args.createIniFilename != None: 237# printLog('Creating Ini files') 238# if os.path.isfile(args.createIniFilename): 239# printLog('A file with the name \'{}\' already exists. Please delete the file or choose another name.'.format(args.createIniFilename)) 240# quit() 241# printLog('Creating Ini file:'+args.createIniFilename+'\n') 242# ini = open(args.createIniFilename, 'w') 243# ini.write('batchSize {} ;'.format(args.batchSize)) 244# ini.write('constProbSize {} ;'.format(args.constProbSize)) 245# ini.write('lengthx {} ;'.format(args.lengthx)) 246# ini.write('lengthy {} ;'.format(args.lengthy)) 247# ini.write('lengthz {} ;'.format(args.lengthz)) 248# ini.write('prime_factor {} ;'.format(args.prime_factor)) 249# ini.write('test_count {} ;'.format(args.test_count)) 250# ini.write('reps {} ;'.format(args.reps)) 251# ini.write('problemsize {} ;'.format(args.problemsize)) 252# ini.write('device {} ;'.format(args.device)) 253# ini.write('inputlayout {} ;'.format(args.inputlayout)) 254# ini.write('outputlayout {} ;'.format(args.outputlayout)) 255# ini.write('placeness {} ;'.format(args.placeness)) 256# ini.write('precision {} ;'.format(args.precision)) 257# printLog('Created Ini file:'+args.createIniFilename+'\n') 258# printLog("=========================MEASURE PERFORMANCE START===========================\n") 259# quit() 260# 261 262#turn pow10 into its range list 263if args.batchSize.count('pow10'): 264 args.batchSize = pow10 265 266#split up comma-delimited lists 267args.batchSize = args.batchSize.split(',') 268args.constProbSize = int(args.constProbSize.split(',')[0]) 269args.device = args.device.split(',') 270args.lengthx = args.lengthx.split(',') 271args.lengthy = args.lengthy.split(',') 272args.lengthz = args.lengthz.split(',') 273args.prime_factor = args.prime_factor.split(',') 274if args.problemsize: 275 args.problemsize = args.problemsize.split(',') 276args.inputlayout = args.inputlayout.split(',') 277args.outputlayout = args.outputlayout.split(',') 278args.placeness = args.placeness.split(',') 279args.precision = args.precision.split(',') 280 281 282 283printLog('Executing for label: '+str(args.label)) 284#check parameters for sanity 285 286# batchSize of 'max' must not be in a list (does not get on well with others) 287#if args.batchSize.count('max') and len(args.batchSize) > 1: 288if ( args.batchSize.count('max') or args.batchSize.count('adapt') )and len(args.batchSize) > 1: 289 printLog('ERROR: --batchsize max must not be in a comma delimited list') 290 quit() 291 292 293# in case of an in-place transform, input and output layouts must be the same (otherwise: *boom*) 294#for n in args.placeness: 295# if n == 'in' or n == 'inplace': 296# if len(args.inputlayout) > 1 or len(args.outputlayout) > 1 or args.inputlayout[0] != args.outputlayout[0]: 297# printLog('ERROR: if transformation is in-place, input and output layouts must match') 298# quit() 299 300# check for valid values in precision 301for n in args.precision: 302 if n != 'single' and n != 'double': 303 printLog('ERROR: invalid value for precision') 304 quit() 305 306def isPrime(n): 307 import math 308 n = abs(n) 309 i = 2 310 while i <= math.sqrt(n): 311 if n%i == 0: 312 return False 313 i += 1 314 return True 315 316def findFactors(number): 317 iter_space = range(1, number+1) 318 prime_factor_list = [] 319 for curr_iter in iter_space: 320 if isPrime(curr_iter) == True: 321 #print 'curr_iter_prime: ', curr_iter 322 if number%curr_iter == 0: 323 prime_factor_list.append(curr_iter) 324 return prime_factor_list 325 326 327#Type : Function 328#Input: num, a number which we need to factorize 329#Return Type: list 330#Details: This function returns only the prime factors on an input number 331# e.g: input: 20, returns: [2,2,5] 332# input: 32, returns: [2,2,2,2,2] 333def factor(num): 334 if num == 1: 335 return [1] 336 i = 2 337 limit = num**0.5 338 while i <= limit: 339 if num % i == 0: 340 ret = factor(num/i) 341 ret.append(i) 342 return ret 343 i += 1 344 return [num] 345 346def validateFactors(flist): 347 ref_list = [1,2,3,5] 348 if flist==ref_list: 349 return True 350 if len(flist) > len(ref_list): 351 return False 352 for felement in flist: 353 if ref_list.count(felement) != 1: 354 return False 355 return True 356 357#Type : Function 358#Input: num, a number which we need to validate for 1,2,3 or 5 factors 359#Return Type: boolean 360#Details: This function validates an input number for its prime factors 361# If factors has number other than 1,2,3 or 5 then return false else return true 362# e.g: input: 20, returns: True 363# input: 28, returns: False 364def validate_number_for_1235(num): 365 if num == 0: 366 return True 367 set1235 = set([1,2,3,5]) 368 setPrimeFactors = set(factor(num)) 369 setPrimeFactors = setPrimeFactors | set1235 #performed union of two sets 370 #if still the sets are same then we are done!!! 371 #else we got few factors other than 1,2,3 or 5 and we should invalidate 372 #the input number 373 if setPrimeFactors == set1235: 374 return True 375 return False 376 377 378def getValidNumbersInRange(rlist): 379 valid_number_list = [] 380 for relement in rlist: 381 prime_factors = findFactors(relement) 382 if validateFactors(prime_factors) == True: 383 valid_number_list.append(relement) 384 return valid_number_list 385 386def get_next_num_with_1235_factors(start): 387 start+=1 388 while not validateFactors(findFactors(start)): 389 start+=1 390 return start 391 392 393def check_number_for_1235_factors(number): 394 #printLog('number:'+ number) 395 factors = findFactors(number) 396 #printLog('factors:'+ factors) 397 if not validateFactors(factors): 398 printLog("ERROR: --{0} must have only 1,2,3,5 as factors") 399 return False 400 return True 401 402 403 404def check_for_1235_factors(values, option): 405 #print 'values: ', values 406 for n in values: 407 for m in n.replace('-',',').split(','): 408 if not validate_number_for_1235(int(m)): 409 print 'ERROR: --{0} must specify number with only 1,2,3,5 as factors'.format(option) 410 quit() 411 #print 'Valid number for :',option,':', m 412 413 414if args.library == 'clFFT': 415 check_for_1235_factors(args.lengthx, 'lengthx') 416 check_for_1235_factors(args.lengthy, 'lengthy') 417 check_for_1235_factors(args.lengthz, 'lengthz') 418 419 420 421if not os.path.isfile(args.prefix+executable(args.library)): 422 printLog("ERROR: Could not find client named {0}".format(executable(args.library))) 423 quit() 424 425 426def get235RadicesNumberInRange(minimum, maximum): 427 if minimum == 0 and maximum == 0: 428 return [0] 429 numbers = generate235Radices(maximum) 430 minIndex = numbers.index(minimum) 431 maxIndex = numbers.index(maximum) 432 return numbers[minIndex:maxIndex+1] 433 434#expand ranges 435class Range: 436 def __init__(self, ranges, defaultStep='+1'): 437 self.expanded = [] 438 for thisRange in ranges: 439 if thisRange != 'max' and thisRange != 'adapt' : 440 if thisRange.count(':'): 441 self._stepAmount = thisRange.split(':')[1] 442 else: 443 self._stepAmount = defaultStep 444 thisRange = thisRange.split(':')[0] 445 446 if self._stepAmount.count('x'): 447 self._stepper = '_mult' 448 self._stepAmount = self._stepAmount.lstrip('+x') 449 self._stepAmount = int(self._stepAmount) 450 elif self._stepAmount.count('l'): 451 self._stepper = '_next_num_with_1235_factor' 452 self._stepAmount = 0 453 else: 454 self._stepper = '_add' 455 self._stepAmount = self._stepAmount.lstrip('+x') 456 self._stepAmount = int(self._stepAmount) 457 458 if thisRange.count('-'): 459 self.begin = int(thisRange.split('-')[0]) 460 self.end = int(thisRange.split('-')[1]) 461 else: 462 self.begin = int(thisRange.split('-')[0]) 463 self.end = int(thisRange.split('-')[0]) 464 self.current = self.begin 465 466 # _thisRangeExpanded = [] 467 if thisRange == 'max': 468 self.expanded = self.expanded + ['max'] 469 elif thisRange == 'adapt': 470 self.expanded = self.expanded + ['adapt'] 471 elif self.begin == 0 and self._stepper == '_mult': 472 self.expanded = self.expanded + [0] 473 else: 474 if self._stepper == '_next_num_with_1235_factor': 475 self.expanded = self.expanded + get235RadicesNumberInRange(self.current, self.end) 476 else: 477 while self.current <= self.end: 478 self.expanded = self.expanded + [self.current] 479 self._step() 480 481 # now we want to uniquify and sort the expanded range 482 self.expanded = list(set(self.expanded)) 483 self.expanded.sort() 484 485 # advance current value to next 486 def _step(self): 487 getattr(self, self._stepper)() 488 489 def _mult(self): 490 self.current = self.current * self._stepAmount 491 492 def _add(self): 493 self.current = self.current + self._stepAmount 494 495 def _next_num_with_1235_factor(self): 496 self.current = get_next_num_with_1235_factors(self.current) 497 498 499args.batchSize = Range(args.batchSize).expanded 500args.lengthx = Range(args.lengthx, 'l').expanded 501args.lengthy = Range(args.lengthy, 'l').expanded 502args.lengthz = Range(args.lengthz, 'l').expanded 503 504 505def create_prime_factors(args,input_list): 506 powers2=[1] 507 powers3=[1] 508 powers5=[1] 509 powers7=[1] 510 if '2' in args.prime_factor: 511 powers2+=[2**x for x in range(1,int(math.floor(math.log(max(input_list),2)+1)))] 512 if '3' in args.prime_factor: 513 powers3+=[3**x for x in range(1,int(math.floor(math.log(max(input_list),3)+1)))] 514 if '5' in args.prime_factor: 515 powers5+=[5**x for x in range(1,int(math.floor(math.log(max(input_list),5)+1)))] 516 if '7' in args.prime_factor: 517 powers7+=[7**x for x in range(1,int(math.floor(math.log(max(input_list),7)+1)))] 518 519 520 xlist=[] 521 for i in powers2: 522 for j in powers3: 523 for k in powers5: 524 for l in powers7: 525 dummy=int(i)*int(j)*int(k)*int(l) 526 if(dummy<=max(input_list)) and (dummy>=min(input_list)): 527 xlist.append(dummy) 528 529 xlist=sorted(xlist) 530 xlist=xlist[:int(args.test_count)] #snafu 531 return xlist 532 533args.lengthx=create_prime_factors(args,args.lengthx) 534args.lengthy=create_prime_factors(args,args.lengthy) 535args.lengthz=create_prime_factors(args,args.lengthz) 536 537#expand problemsizes ('XxYxZ:batch') 538#print "args.problemsize--1-->", args.problemsize 539if args.problemsize and args.problemsize[0] != 'None': 540 i = 0 541 while i < len(args.problemsize): 542 args.problemsize[i] = args.problemsize[i].split(':') 543 args.problemsize[i][0] = args.problemsize[i][0].split('x') 544 i = i+1 545 546 547#create the problem size combinations for each run of the client 548# A: This part creats a product of all possible combinations. Too many cases in 2/3D 549#problem_size_combinations = itertools.product(args.lengthx, args.lengthy, args.lengthz, args.batchSize) 550#problem_size_combinations = list(itertools.islice(problem_size_combinations, None)) 551 552if args.lengthy[0]==1: 553 args.lengthy=[1]*len(args.lengthx) 554if args.lengthz[0]==1: 555 args.lengthz=[1]*len(args.lengthx) 556 557dummy=[args.batchSize[0]]*len(args.lengthx) 558problem_size_combinations=zip(args.lengthx,args.lengthy,args.lengthz,dummy) 559 560#print "args.problemsize--2-->", args.problemsize 561#add manually entered problem sizes to the list of FFTs to crank out 562manual_test_combinations = [] 563if args.problemsize and args.problemsize[0] != 'None': 564 for n in args.problemsize: 565 x = [] 566 y = [] 567 z = [] 568 batch = [] 569 570 x.append(int(n[0][0])) 571 572 if len(n[0]) >= 2: 573 y.append(int(n[0][1])) 574 else: 575 y.append(1) 576 577 if len(n[0]) >= 3: 578 z.append(int(n[0][2])) 579 else: 580 z.append(1) 581 582 if len(n) > 1: 583 batch.append(int(n[1])) 584 else: 585 batch.append(1) 586 587 combos = itertools.product(x, y, z, batch) 588 combos = list(itertools.islice(combos, None)) 589 for n in combos: 590 manual_test_combinations.append(n) 591 # manually entered problem sizes should not be plotted (for now). they may still be output in a table if requested 592 593 594problem_size_combinations = problem_size_combinations + manual_test_combinations 595 596#create final list of all transformations (with problem sizes and transform properties) 597test_combinations = itertools.product(problem_size_combinations, args.device, args.inputlayout, args.outputlayout, args.placeness, args.precision) 598test_combinations = list(itertools.islice(test_combinations, None)) 599test_combinations = [TestCombination(params[0][0], params[0][1], params[0][2], params[0][3], params[1], params[2], params[3], params[4], params[5], args.label) for params in test_combinations] 600 601if args.iniFilename != None: 602 array=np.genfromtxt(args.iniFilename, names=True, delimiter=',', dtype=None) 603 test_combinations = [TestCombination(params[0],params[1], params[2], params[3], params[4],params[5],params[6],params[7],params[8],args.label) for params in array] 604 605#print("lenghtx= ",test_combinations[0].x) 606#print("lenghty= ",test_combinations[0].y) 607#print("lenghtz= ",test_combinations[0].z) 608#print("placeness= ",test_combinations[0].placeness) 609 610 611 612#turn each test combination into a command, run the command, and then stash the gflops 613result = [] # this is where we'll store the results for the table 614 615 616#open output file and write the header 617 618if args.tableOutputFilename == None: 619 if args.library == 'cuFFT': 620 args.tableOutputFilename = 'cuFFT_' + 'x_'+ str(args.lengthx[0]) + '_y_'+str(args.lengthy[0])+'_z_'+str(args.lengthz[0])+'_'+str(args.precision[0]) +'_'+datetime.now().isoformat().replace(':','.') + '.txt' 621 elif args.library=='clFFT': 622 args.tableOutputFilename = 'clFFT_' + 'x_'+ str(args.lengthx[0]) + '_y_'+str(args.lengthy[0])+'_z_'+str(args.lengthz[0])+'_'+str(args.precision[0])+ '_'+datetime.now().isoformat().replace(':','.') + '.txt' 623else: 624 if os.path.isfile(args.tableOutputFilename): 625 oldname = args.tableOutputFilename 626 args.tableOutputFilename = args.tableOutputFilename + datetime.now().isoformat().replace(':','.') 627 message = 'A file with the name ' + oldname + ' already exists. Changing filename to ' + args.tableOutputFilename 628 printLog(message) 629 630 631printLog('table header---->'+ str(tableHeader)) 632 633table = open(args.tableOutputFilename, 'w') 634table.write(tableHeader + '\n') 635table.flush() 636if args.constProbSize == -1: 637 args.constProbSize = maxBatchSize(1, 1, 1, args.inputlayout[0], args.precision[0], executable(args.library), '-' + args.device[0]) 638args.constProbSize = int(args.constProbSize) 639 640 641printLog('Total combinations = '+str(len(test_combinations))) 642 643vi = 0 644for params in test_combinations: 645 if vi>=int(args.test_count): 646 break 647 vi = vi+1 648 printLog("") 649 printLog('preparing command: '+ str(vi)) 650 device = params.device 651 lengthx = str(params.x) 652 lengthy = str(params.y) 653 lengthz = str(params.z) 654 inlayout=str(params.inlayout) 655 outlayout=str(params.outlayout) 656 prefix=str(args.prefix) 657 658 659 if params.batchsize == 'max': 660 batchSize = maxBatchSize(lengthx, lengthy, lengthz, params.inlayout, params.precision, executable(args.library), '-' + device) 661 elif params.batchsize == 'adapt': 662 batchSize = str(args.constProbSize/(int(lengthx)*int(lengthy)*int(lengthz))) 663 else: 664 batchSize = str(params.batchsize) 665 666 if params.placeness == 'inplace' or params.placeness == 'in': 667 placeness = '' 668 elif params.placeness == 'outofplace' or params.placeness == 'out': 669 placeness = '--outPlace' 670 else: 671 printLog('ERROR: invalid value for placeness when assembling client command') 672 673 if params.precision == 'single': 674 precision = '' 675 elif params.precision == 'double': 676 precision = '--double' 677 else: 678 printLog('ERROR: invalid value for precision when assembling client command') 679 680 681 #set up arguments here 682 if args.library == 'clFFT': 683 arguments = [prefix+ executable(args.library), 684 '-' + device, 685 '-x', lengthx, 686 '-y', lengthy, 687 '-z', lengthz, 688 '--batchSize', batchSize, 689 '--inLayout', inlayout, 690 '--outLayout',outlayout, 691 placeness, 692 precision, 693 '-p', args.reps] 694 elif args.library == 'cuFFT': 695 if inlayout[0]=='1' and outlayout[0]=='1': 696 cuFFT_type='1' 697 elif inlayout[0]=='3' and outlayout[0]=='5': 698 cuFFT_type='3' 699 elif inlayout[0]=='5' and outlayout[0]=='3': 700 cuFFT_type='2' 701 else: 702 print"Wrong input/outputlayout. Only C2C/R2C/C2R are supported for Cuda" 703 exit() 704 arguments=[prefix+executable(args.library), 705 '-x', lengthx, 706 '-y', lengthy, 707 '-z', lengthz, 708 '-b', batchSize, 709 '-p',args.reps, 710 '-d',str(int(args.precision[0]=='double')), 711 '-type',cuFFT_type] 712 713 writeline = True 714 try: 715 arguments=' '.join(arguments) 716 printLog('Executing Command: '+str(arguments)) 717 output = checkTimeOutPut(arguments) 718 output = output.split(os.linesep); 719 printLog('Execution Successfull---------------\n') 720 721 except errorHandler.ApplicationException as ae: 722 writeline = False 723 printLog('ERROR: Command is taking too much of time '+ae.message+'\n'+'Command: \n'+str(arguments)) 724 continue 725 except subprocess.CalledProcessError as clientCrash: 726 print 'Command execution failure--->' 727 if clientCrash.output.count('CLFFT_INVALID_BUFFER_SIZE'): 728 writeline = False 729 printLog('Omitting line from table - problem is too large') 730 else: 731 writeline = False 732 printLog('ERROR: client crash. Please report the following error message (with \'CLFFT_*\' error code, if given, and the parameters used to invoke measurePerformance.py) \n'+clientCrash.output+'\n') 733 printLog('IN ORIGINAL WE CALL QUIT HERE - 1\n') 734 continue 735 736 for x in output: 737 if x.count('out of memory'): 738 writeline = False 739 printLog('ERROR: Omitting line from table - problem is too large') 740 741 if writeline: 742 try: 743 if args.library == 'cuFFT': 744 output = itertools.ifilter( lambda x: x.count('gflops'), output) 745 else: 746 output = itertools.ifilter( lambda x: x.count('gflops'), output) 747 748 output = list(itertools.islice(output, None)) 749 thisResult = re.search('\d+\.*\d*e*-*\d*$', output[-1]) 750 if args.library == 'cuFFT': 751 thisResult = re.search('[-+]?\d*\.\d+|\d+$', output[-1]) 752 thisResult = float(thisResult.group(0)) 753 754 thisResult = (params.x, params.y, params.z, batchSize, params.device, params.inlayout, params.outlayout, params.placeness, params.precision, params.label, thisResult) 755 756 outputRow = '' 757 for x in thisResult: 758 outputRow = outputRow + str(x) + ',' 759 outputRow = outputRow.rstrip(',') 760 table.write(outputRow + '\n') 761 table.flush() 762 except: 763 printLog('ERROR: Exception occurs in GFLOP parsing') 764 else: 765 if(len(output) > 0): 766 if output[0].find('nan') or output[0].find('inf'): 767 printLog( 'WARNING: output from client was funky for this run. skipping table row') 768 else: 769 prinLog('ERROR: output from client makes no sense') 770 printLog(str(output[0])) 771 printLog('IN ORIGINAL WE CALL QUIT HERE - 2\n') 772 else: 773 prinLog('ERROR: output from client makes no sense') 774 #quit() 775printLog("=========================MEASURE PERFORMANCE ENDS===========================\n") 776# 777#""" 778#print a pretty table 779#""" 780#if args.tableOutputFilename == None: 781# args.tableOutputFilename = 'results' + datetime.now().isoformat().replace(':','.') + '.txt' 782#else: 783# if os.path.isfile(args.tableOutputFilename): 784# oldname = args.tableOutputFilename 785# args.tableOutputFilename = args.tableOutputFilename + datetime.now().isoformat().replace(':','.') 786# message = 'A file with the name ' + oldname + ' already exists. Changing filename to ' + args.tableOutputFilename 787# print message 788# 789#table = open(args.tableOutputFilename, 'w') 790#table.write(tableHeader + '\n') 791#for x in result: 792# row = '' 793# for y in x: 794# row = row + str(y) + ',' 795# row = row[:-1] #chomp off the trailing comma 796# table.write(row + '\n') 797