run-sniper 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. #!/usr/bin/env python
  2. import sys, os, time, getopt, pipes, tempfile, traceback
  3. sys.path.append(os.path.join(os.path.dirname(__file__), 'tools', 'scheduler'))
  4. import graphite_tools
  5. sys.path.append(os.path.join(os.path.dirname(__file__), 'tools', 'python'))
  6. import env_setup_bm
  7. sys.path.append(os.path.join(env_setup_bm.sniper_root(), 'tools'))
  8. import run_sniper
  9. abspath = lambda d: os.path.abspath(os.path.join(d))
  10. HOME = abspath(os.path.dirname(__file__))
  11. from suites import modules
  12. def usage():
  13. print 'Run benchmark under the Sniper simulator'
  14. print 'Usage:'
  15. print ' %s -p <program> -i <inputsize (test)> -n <ncores (1)> -m <machines (1)> -d <outputdir (.)> -c <config-file> -r <sniper-root-dir> -g <options>' % sys.argv[0]
  16. print 'Benchmarks:'
  17. for module in sorted(modules):
  18. module = __import__(module)
  19. print ' ', module.__name__ + ':'
  20. try:
  21. print ' ', ' '.join(module.allbenchmarks())
  22. except TypeError:
  23. print 'INFO: %s not downloaded yet, run make to download its components.' % module.__name__
  24. sys.exit(2)
  25. program = ''
  26. inputsize = 'test'
  27. benchmark_options = []
  28. ncores = None
  29. machines = 'localhost'
  30. outputdir = '.'
  31. rungraphiteoptions = []
  32. graphiterootdir = env_setup_bm.sniper_root()
  33. roi_only = True
  34. roi_script = False
  35. sim_end = None
  36. saverun = False
  37. saverun_prefix = ''
  38. saverun_second_stage = False
  39. benchmarks = []
  40. verbose = False
  41. if not sys.argv[1:]:
  42. usage()
  43. opts_passthrough = [ 'profile', 'perf', 'gdb', 'gdb-wait', 'gdb-quit', 'appdebug', 'appdebug-manual', 'appdebug-enable', 'power', 'cache-only', 'fast-forward', 'no-cache-warming', 'save-patch', 'pin-stats', 'viz', 'viz-aso', 'wrap-sim=', 'sift' ]
  44. try:
  45. opts, args = getopt.getopt(sys.argv[1:], "hvp:i:B:n:m:s:d:c:r:g:", [ "no-roi", "roi-script", "roi", "sim-end=", "save-run", "save-run-prefix=", "save-run-second-stage=", "benchmarks=" ] + opts_passthrough)
  46. except getopt.GetoptError, e:
  47. # print help information and exit:
  48. print e
  49. usage()
  50. for o, a in opts:
  51. if o == '-h':
  52. usage()
  53. sys.exit()
  54. if o == '-v':
  55. verbose = True
  56. rungraphiteoptions.append('-v')
  57. if o == '-p':
  58. program = a
  59. if o == '-i':
  60. inputsize = a
  61. if o == '-B':
  62. benchmark_options.append(a)
  63. if o == '-n':
  64. ncores = int(a)
  65. if o == '-m':
  66. machines = a
  67. if o == '-s':
  68. rungraphiteoptions.append('-s ' + pipes.quote(a))
  69. if o == '-d':
  70. outputdir = a
  71. if o == '-c':
  72. cfgs = []
  73. for cfg in a.split(','):
  74. if os.path.isfile(cfg):
  75. cfg = os.path.abspath(os.path.join(cfg))
  76. elif os.path.isfile(cfg+'.cfg'):
  77. cfg = os.path.abspath(os.path.join(cfg+'.cfg'))
  78. cfgs.append(cfg)
  79. rungraphiteoptions.append('-c ' + pipes.quote(','.join(cfgs)))
  80. if o == '-g':
  81. rungraphiteoptions.append('-g ' + pipes.quote(a))
  82. if o == '-r':
  83. graphiterootdir = a
  84. if o == '--no-roi':
  85. roi_only = False
  86. if o == '--roi-script':
  87. roi_script = True
  88. roi_only = False
  89. if o == '--roi':
  90. # --roi is the default so it isn't really needed, but if we remove it from getopt's list,
  91. # it will interpret --roi as a prefix for --roi-script which will be completely wrong
  92. roi_only = True
  93. if o == '--sim-end':
  94. sim_end = a
  95. rungraphiteoptions.append('--sim-end=%s' % sim_end)
  96. if o == '--save-run':
  97. saverun = True
  98. if o == '--save-run-prefix':
  99. saverun = True
  100. saverun_prefix = a+'-'
  101. if o == '--save-run-second-stage':
  102. saverun_second_stage = a
  103. if o.startswith('--') and o[2:] in opts_passthrough:
  104. rungraphiteoptions.append(o)
  105. if o.startswith('--') and o[2:]+'=' in opts_passthrough:
  106. rungraphiteoptions.append('%s="%s"' % (o, a))
  107. if o == '--benchmarks':
  108. for bm in a.split(','):
  109. benchmarks.append(bm.split('-'))
  110. if not ncores:
  111. ncores = sum([ int(app_nthreads) for package, programname, inputsize, app_nthreads in benchmarks ])
  112. if ncores is None:
  113. # Keep ncores as None while scanning options, so --benchmarks can set a default overriden by -n
  114. ncores = 1
  115. if not graphiterootdir:
  116. print '\nERROR: The SNIPER_ROOT or GRAPHITE_ROOT environment variable has not been set. Please set it to continue.\n'
  117. sys.exit(1)
  118. if not os.path.exists(os.path.realpath(os.path.join(graphiterootdir, 'run-sniper'))):
  119. print '\nERROR: The SNIPER_ROOT or GRAPHITE_ROOT environment variable has been set to the wrong directory. Please set it to a directory containing Sniper to continue.\n'
  120. sys.exit(1)
  121. if not os.path.exists(os.path.realpath(os.path.join(graphiterootdir, 'lib', 'pin_sim.so'))):
  122. print '\nERROR: Sniper has not been compiled. Please compile Sniper before trying to run an application.\n'
  123. sys.exit(1)
  124. # This command will always succeed
  125. benchmarksrootdir = env_setup_bm.benchmarks_root()
  126. os.putenv('BENCHMARKS_ROOT', benchmarksrootdir)
  127. if not graphiterootdir:
  128. print '\nERROR: The SNIPER_ROOT or GRAPHITE_ROOT environment variable has not been set. Please set it to continue.\n'
  129. sys.exit(1)
  130. if not os.path.exists(os.path.realpath(os.path.join(graphiterootdir, 'run-sniper'))):
  131. print '\nERROR: The SNIPER_ROOT or GRAPHITE_ROOT environment variable has been set to the wrong directory. Please set it to a directory containing Sniper to continue.\n'
  132. sys.exit(1)
  133. if not os.path.exists(os.path.realpath(os.path.join(graphiterootdir, 'lib', 'pin_sim.so'))):
  134. print '\nERROR: Sniper has not been compiled. Please compile Sniper before trying to run an application.\n'
  135. sys.exit(1)
  136. # Create the output directory if it doesn't already exist
  137. outputdir = os.path.realpath(outputdir)
  138. if not os.path.exists(outputdir):
  139. try:
  140. os.makedirs(outputdir)
  141. except OSError:
  142. print >> sys.stderr, 'Failed to create output directory', outputdir
  143. sys.exit(1)
  144. if saverun_second_stage:
  145. outputdir = saverun_second_stage
  146. elif saverun:
  147. # Create the base directory
  148. runpathbase = os.path.join(os.getenv('BENCHMARKS_ROOT'),'runs','%s-%s-%s'%(program,inputsize,ncores))
  149. os.system('mkdir -p "%s"' % abspath(runpathbase))
  150. # Find the next available run directory
  151. runnum = 1
  152. while True:
  153. runpath = os.path.join(runpathbase,saverun_prefix+str(runnum))
  154. if os.path.exists(runpath):
  155. runnum = runnum+1
  156. else:
  157. break
  158. # Use this run directory
  159. outputdir = abspath(runpath)
  160. os.system('mkdir -p "%s"' % outputdir)
  161. # Update the symlink to the latest entry
  162. symlink = os.path.join(runpathbase,'latest')
  163. try:
  164. os.remove(symlink)
  165. except:
  166. pass
  167. os.symlink(str(runnum),symlink)
  168. print '[SNIPER] Saving run to', runpath
  169. # Now run run-sniper again, with the directory we've just chosen, redirecting stdout and stderr
  170. cmd = ' '.join(map(pipes.quote, sys.argv)) \
  171. + ' --save-run-second-stage=%s' % pipes.quote(outputdir) \
  172. + ' > >(tee %s)' % pipes.quote(os.path.join(outputdir, 'stdout.txt')) \
  173. + ' 2> >(tee %s >&2)' % pipes.quote(os.path.join(outputdir, 'stderr.txt'))
  174. os.system('bash -c %s' % pipes.quote(cmd))
  175. sys.exit(0)
  176. # Sanity check: when no -r option is present to explicitly select a Graphite directory,
  177. # and the current directory contains a Graphite binary that's not the same (after removing symlinks, etc.)
  178. # as the one pointed to by GRAPHITE_ROOT, then we're probably in a branch but forgot to reset GRAPHITE_ROOT
  179. if graphiterootdir == (os.getenv('SNIPER_ROOT') or os.getenv('GRAPHITE_ROOT')):
  180. graphite_selected = os.path.realpath(os.path.join(graphiterootdir, 'lib', 'pin_sim.so'))
  181. graphite_here = os.path.realpath(os.path.join('lib', 'pin_sim.so'))
  182. if os.path.exists(graphite_here) and graphite_selected != graphite_here:
  183. print '\nWARNING: Sniper binary found in current directory, but set to use SNIPER_ROOT which points elsewhere!\n'
  184. print ' current directory =', os.getcwd()
  185. print ' using SNIPER_ROOT/GRAPHITE_ROOT =', (os.getenv('SNIPER_ROOT') or os.getenv('GRAPHITE_ROOT'))
  186. print ''
  187. time.sleep(5)
  188. # Explicitly set both SNIPER_ROOT and GRAPHITE_ROOT to the selected directory to avoid
  189. # confusion in scripts that use either one or the other
  190. os.putenv('SNIPER_ROOT', graphiterootdir)
  191. os.putenv('GRAPHITE_ROOT', graphiterootdir)
  192. if roi_only:
  193. if benchmarks:
  194. pass # record-trace will only send ROI instructions through SIFT,
  195. # Sniper itself must process all of them in detailed mode
  196. else:
  197. rungraphiteoptions.append('--roi')
  198. if roi_script:
  199. rungraphiteoptions.append('--roi-script')
  200. # Pass current directory to Sniper, which can use it to find more script files
  201. # (By the time sniper/run-sniper gets called, the benchmark's runner script most likely has already changed the current directory)
  202. rungraphiteoptions.append('--curdir=' + pipes.quote(os.getcwd()))
  203. if not program and not benchmarks:
  204. usage()
  205. if benchmarks:
  206. rungraphiteoptions.append('--trace-manual')
  207. rungraphiteoptions.append('-g --traceinput/enabled=true')
  208. rungraphiteoptions.append('-g --traceinput/emulate_syscalls=true')
  209. rungraphiteoptions.append('-g --traceinput/num_apps=%u' % len(benchmarks))
  210. basefname = 'run_benchmarks'
  211. tracetempdir = tempfile.mkdtemp()
  212. tracefiles_created = [] # FIFOs to be cleaned up
  213. traceprefix = os.path.join(tracetempdir, basefname)
  214. rungraphiteoptions.append('-g --traceinput/trace_prefix=%s' % traceprefix)
  215. # Create FIFOs for first thread of each application
  216. for p in range(len(benchmarks)):
  217. for f in ('','_response'):
  218. filename = '%s%s.app%d.th%d.sift' % (traceprefix, f, p, 0)
  219. os.mkfifo(filename)
  220. tracefiles_created.append(filename)
  221. outputdir = abspath(outputdir)
  222. os.chdir(outputdir)
  223. os.environ['LD_LIBRARY_PATH'] = '%s:%s/libs' % (os.environ.get('LD_LIBRARY_PATH', ''), HOME)
  224. runcmd = abspath(os.path.join(graphiterootdir, 'run-sniper'))
  225. try:
  226. rc=1
  227. if not benchmarks:
  228. package, program = program.rsplit("-",1)
  229. if '-' in inputsize:
  230. inputsize, nthreads = inputsize.rsplit('-', 1)
  231. nthreads = int(nthreads)
  232. benchmark_options.append('force_nthreads')
  233. else:
  234. nthreads = ncores
  235. program = __import__(package).Program(program, nthreads, inputsize, benchmark_options)
  236. snipercmd = 'SNIPER_APP_LD_PRELOAD=$LD_PRELOAD; unset LD_PRELOAD; ' # Allow benchmarks that require LD_PRELOAD to work inside of Sniper
  237. snipercmd += "%(runcmd)s -n %(ncores)u -m '%(machines)s' -d '%(outputdir)s'" % locals()
  238. snipercmd += ' ' + ' '.join(rungraphiteoptions)
  239. snipercmd += ' ' + program.rungraphiteoptions()
  240. snipercmd += ' -- '
  241. rc = program.run(snipercmd)
  242. else:
  243. snipercmd = "%(runcmd)s -n %(ncores)u -m '%(machines)s' -d '%(outputdir)s'" % locals()
  244. snipercmd += ' ' + ' '.join(rungraphiteoptions)
  245. applications = []
  246. for app_id, (package, programname, inputsize, app_nthreads) in enumerate(benchmarks):
  247. program = __import__(package).Program(programname, int(app_nthreads), inputsize, ['force_nthreads'])
  248. if program.rungraphiteoptions():
  249. print 'Program', programname, 'requires simulator options to run. This is currently unsupported.'
  250. sys.exit(1)
  251. tracecmd = '%s %s --routine-tracing -o %s -e 1 -r 1 -s %u %s -- ' % (os.path.join(graphiterootdir, 'record-trace'), verbose and '-v' or '', os.path.join(tracetempdir,basefname), app_id, roi_only and '--roi' or '')
  252. applications.append({'app_id': app_id, 'func': program.run, 'args': tracecmd })
  253. rc = run_sniper.run_multi(snipercmd, applications, repeat = (sim_end or 'first').endswith('-restart'), outputdir = outputdir)
  254. # Cleanup the pipes and temporary directory
  255. for f in tracefiles_created:
  256. try:
  257. os.unlink(f)
  258. except OSError:
  259. pass
  260. try:
  261. os.rmdir(tracetempdir)
  262. except OSError:
  263. pass
  264. sys.exit(rc)
  265. except KeyboardInterrupt, e:
  266. print >> sys.stderr, '\nCtrl-C detected: Killing all child processes'
  267. graphite_tools.kill_children()
  268. sys.exit(-1)
  269. except Exception, e:
  270. print e
  271. traceback.print_exc(file=sys.stdout)
  272. graphite_tools.kill_children()
  273. sys.exit(-1)