2 from __future__
import print_function
5 from Configuration.PyReleaseValidation.MatrixReader
import MatrixReader
6 from Configuration.PyReleaseValidation.MatrixRunner
import MatrixRunner
7 from Configuration.PyReleaseValidation.MatrixInjector
import MatrixInjector,performInjectionOptionTest
14 mrd.showRaw(opt.useInput, opt.refRel, opt.fromScratch, opt.raw, opt.step1Only, selected=opt.testList)
23 mrd.prepare(opt.useInput, opt.refRel, opt.fromScratch)
27 definedWf = [dwf.numId
for dwf
in mrd.workFlows]
28 definedSet = set(definedWf)
29 testSet = set(opt.testList)
30 undefSet = testSet - definedSet
31 if len(undefSet)>0:
raise ValueError(
'Undefined workflows: '+
', '.
join(
map(str,list(undefSet))))
32 duplicates = [wf
for wf
in testSet
if definedWf.count(wf)>1 ]
33 if len(duplicates)>0:
raise ValueError(
'Duplicated workflows: '+
', '.
join(
map(str,list(duplicates))))
37 mrd.show(opt.testList, opt.extended, opt.cafVeto)
38 if opt.testList :
print(
'selected items:', opt.testList)
40 mRunnerHi =
MatrixRunner(mrd.workFlows, opt.nProcs, opt.nThreads)
41 ret = mRunnerHi.runTests(opt)
45 print(
'Cannot go on with wmagent injection with failing workflows')
47 wfInjector =
MatrixInjector(opt,mode=opt.wmcontrol,options=opt.wmoptions)
48 ret= wfInjector.prepare(mrd,
57 if __name__ ==
'__main__':
140 'jetmc': [5.1, 13, 15, 25, 38, 39],
141 'metmc' : [5.1, 15, 25, 37, 38, 39],
142 'muonmc' : [5.1, 124.4, 124.5, 20, 21, 22, 23, 25, 30],
147 usage =
'usage: runTheMatrix.py --show -s ' 149 parser = argparse.ArgumentParser(usage,formatter_class=argparse.ArgumentDefaultsHelpFormatter)
151 parser.add_argument(
'-b',
'--batchName',
152 help=
'relval batch: suffix to be appended to Campaign name',
156 parser.add_argument(
'-m',
'--memoryOffset',
157 help=
'memory of the wf for single core',
162 parser.add_argument(
'--addMemPerCore',
163 help=
'increase of memory per each n > 1 core: memory(n_core) = memoryOffset + (n_core-1) * memPerCore',
168 parser.add_argument(
'-j',
'--nproc',
169 help=
'number of processes. 0 Will use 4 processes, not execute anything but create the wfs',
174 parser.add_argument(
'-t',
'--nThreads',
175 help=
'number of threads per process to use in cmsRun.',
180 parser.add_argument(
'--nStreams',
181 help=
'number of streams to use in cmsRun.',
186 parser.add_argument(
'--nEvents',
187 help=
'number of events to process in cmsRun. If 0 will use the standard 10 events.',
192 parser.add_argument(
'--numberEventsInLuminosityBlock',
193 help=
'number of events in a luminosity block',
194 dest=
'numberEventsInLuminosityBlock',
198 parser.add_argument(
'-n',
'--showMatrix',
199 help=
'Only show the worflows. Use --ext to show more',
204 parser.add_argument(
'-e',
'--extended',
205 help=
'Show details of workflows, used with --show',
210 parser.add_argument(
'-s',
'--selected',
211 help=
'Run a pre-defined selected matrix of wf. Deprecated, please use -l limited',
216 parser.add_argument(
'-l',
'--list',
217 help=
'Comma separated list of workflow to be shown or ran. Possible keys are also '+
str(predefinedSet.keys())+
'. and wild card like muon, or mc',
221 parser.add_argument(
'-f',
'--failed-from',
222 help=
'Provide a matrix report to specify the workflows to be run again. Augments the -l option if specified already',
226 parser.add_argument(
'-r',
'--raw',
227 help=
'Temporary dump the .txt needed for prodAgent interface. To be discontinued soon. Argument must be the name of the set (standard, pileup,...)',
230 parser.add_argument(
'-i',
'--useInput',
231 help=
'Use recyling where available. Either all, or a comma separated list of wf number.',
233 type=
lambda x: x.split(
','),
236 parser.add_argument(
'-w',
'--what',
237 help=
'Specify the set to be used. Argument must be the name of a set (standard, pileup,...) or multiple sets separated by commas (--what standard,pileup )',
241 parser.add_argument(
'--step1',
242 help=
'Used with --raw. Limit the production to step1',
246 parser.add_argument(
'--maxSteps',
247 help=
'Only run maximum on maxSteps. Used when we are only interested in first n steps.',
252 parser.add_argument(
'--fromScratch',
253 help=
'Comma separated list of wf to be run without recycling. all is not supported as default.',
255 type=
lambda x: x.split(
','),
258 parser.add_argument(
'--refRelease',
259 help=
'Allow to modify the recycling dataset version',
263 parser.add_argument(
'--wmcontrol',
264 help=
'Create the workflows for injection to WMAgent. In the WORKING. -wmcontrol init will create the the workflows, -wmcontrol test will dryRun a test, -wmcontrol submit will submit to wmagent',
265 choices=[
'init',
'test',
'submit',
'force'],
269 parser.add_argument(
'--revertDqmio',
270 help=
'When submitting workflows to wmcontrol, force DQM outout to use pool and not DQMIO',
271 choices=[
'yes',
'no'],
275 parser.add_argument(
'--optionswm',
276 help=
'Specify a few things for wm injection',
280 parser.add_argument(
'--keep',
281 help=
'allow to specify for which comma separated steps the output is needed',
284 parser.add_argument(
'--label',
285 help=
'allow to give a special label to the output dataset name',
288 parser.add_argument(
'--command',
289 help=
'provide a way to add additional command to all of the cmsDriver commands in the matrix',
294 parser.add_argument(
'--apply',
295 help=
'allow to use the --command only for 1 comma separeated',
299 parser.add_argument(
'--workflow',
300 help=
'define a workflow to be created or altered from the matrix',
305 parser.add_argument(
'--dryRun',
306 help=
'do not run the wf at all',
311 parser.add_argument(
'--testbed',
312 help=
'workflow injection to cmswebtest (you need dedicated rqmgr account)',
317 parser.add_argument(
'--noCafVeto',
318 help=
'Run from any source, ignoring the CAF label',
321 action=
'store_false')
323 parser.add_argument(
'--overWrite',
324 help=
'Change the content of a step for another. List of pairs.',
328 parser.add_argument(
'--noRun',
329 help=
'Remove all run list selection from wfs',
334 parser.add_argument(
'--das-options',
335 help=
'Options to be passed to dasgoclient.',
340 parser.add_argument(
'--job-reports',
341 help=
'Dump framework job reports',
346 parser.add_argument(
'--ibeos',
347 help=
'Use IB EOS site configuration',
352 parser.add_argument(
'--sites',
353 help=
'Run DAS query to get data from a specific site. Set it to empty string to search all sites.',
355 default=
'T2_CH_CERN',
358 parser.add_argument(
'--interactive',
359 help=
"Open the Matrix interactive shell",
363 parser.add_argument(
'--dbs-url',
364 help=
'Overwrite DbsUrl value in JSON submitted to ReqMgr2',
369 gpugroup = parser.add_argument_group(
'GPU-related options',
'These options are only meaningful when --gpu is used, and is not set to forbidden.')
371 gpugroup.add_argument(
'--gpu',
'--requires-gpu',
372 help=
'Enable GPU workflows. Possible options are "forbidden" (default), "required" (implied if no argument is given), or "optional".',
374 choices=[
'forbidden',
'optional',
'required'],
380 gpugroup.add_argument(
'--gpu-memory',
381 help=
'Specify the minimum amount of GPU memory required by the job, in MB.',
386 gpugroup.add_argument(
'--cuda-capabilities',
387 help=
'Specify a comma-separated list of CUDA "compute capabilities", or GPU hardware architectures, that the job can use.',
388 dest=
'CUDACapabilities',
389 type=
lambda x: x.split(
','),
390 default=
'6.0,6.1,6.2,7.0,7.2,7.5,8.0,8.6')
393 cudart_version =
None 394 libcudart = os.path.realpath(os.path.expandvars(
'$CMSSW_RELEASE_BASE/external/$SCRAM_ARCH/lib/libcudart.so'))
395 if os.path.isfile(libcudart):
396 cudart_basename = os.path.basename(libcudart)
397 cudart_version =
'.'.
join(cudart_basename.split(
'.')[2:4])
398 gpugroup.add_argument(
'--cuda-runtime',
399 help=
'Specify major and minor version of the CUDA runtime used to build the application.',
401 default=cudart_version)
403 gpugroup.add_argument(
'--force-gpu-name',
404 help=
'Request a specific GPU model, e.g. "Tesla T4" or "NVIDIA GeForce RTX 2080". The default behaviour is to accept any supported GPU.',
408 gpugroup.add_argument(
'--force-cuda-driver-version',
409 help=
'Request a specific CUDA driver version, e.g. 470.57.02. The default behaviour is to accept any supported CUDA driver version.',
410 dest=
'CUDADriverVersion',
413 gpugroup.add_argument(
'--force-cuda-runtime-version',
414 help=
'Request a specific CUDA runtime version, e.g. 11.4. The default behaviour is to accept any supported CUDA runtime version.',
415 dest=
'CUDARuntimeVersion',
418 opt = parser.parse_args()
419 if opt.command: opt.command =
' '.
join(opt.command)
420 os.environ[
"CMSSW_DAS_QUERY_SITES"]=opt.dasSites
423 with open(opt.failed_from,
'r') as report: 424 for report_line
in report:
425 if 'FAILED' in report_line:
426 to_run,_=report_line.split(
'_',1)
427 rerunthese.append(to_run)
429 opt.testList+=
','.
join([
'']+rerunthese)
431 opt.testList =
','.
join(rerunthese)
434 os.environ[
"CMSSW_USE_IBEOS"]=
"true" 436 print(
'Deprecated, please use -l limited')
437 if opt.testList: opt.testList+=
',limited' 438 else: opt.testList=
'limited' 446 opt.apply=
map(stepOrIndex,opt.apply.split(
','))
448 opt.keep=
map(stepOrIndex,opt.keep.split(
','))
452 for entry
in opt.testList.split(
','):
453 if not entry:
continue 455 for k
in predefinedSet:
456 if k.lower().startswith(entry.lower())
or k.lower().endswith(entry.lower()):
457 testList.extend(predefinedSet[k])
462 testList.append(
float(entry))
464 print(entry,
'is not a possible selected entry')
466 opt.testList = list(set(testList))
471 opt.overWrite=eval(opt.overWrite)
474 from colorama
import Fore, Style
475 from os
import isatty
480 intro =
"Welcome to the Matrix (? for help)" 484 cmd.Cmd.__init__(self)
489 for what
in tmp.files:
490 what = what.replace(
'relval_',
'')
491 self.
opt_.what = what
494 self.
opt_.fromScratch)
498 """Clear the screen, put prompt at the top""" 502 print(
"Leaving the Matrix")
506 if inp ==
'x' or inp ==
'q':
509 is_pipe =
not isatty(sys.stdin.fileno())
510 print(Fore.RED +
"Error: " + Fore.RESET +
"unrecognized command.")
516 print(
"\n".
join([
"predefined [predef1 [...]]\n",
517 "Run w/o argument, it will print the list of known predefined workflows.",
518 "Run with space-separated predefined workflows, it will print the workflow-ids registered to them"]))
521 if text
and len(text) > 0:
522 return [t
for t
in predefinedSet.keys()
if t.startswith(text)]
524 return predefinedSet.keys()
527 """Print the list of predefined workflows""" 528 print(
"List of predefined workflows")
530 for w
in arg.split():
531 if w
in predefinedSet.keys():
532 print(
"Predefined Set: %s" % w)
533 print(predefinedSet[w])
535 print(
"Unknown Set: %s" % w)
537 print(
"[ " + Fore.RED +
", ".
join([
str(k)
for k
in predefinedSet.keys()]) + Fore.RESET +
" ]")
540 print(
"\n".
join([
"showWorkflow [workflow1 [...]]\n",
541 "Run w/o arguments, it will print the list of registered macro-workflows.",
542 "Run with space-separated workflows, it will print the full list of workflow-ids registered to them"]))
545 if text
and len(text) > 0:
546 return [t
for t
in self.
matrices_.
keys()
if t.startswith(text)]
552 print(
"Available workflows:")
554 print(Fore.RED + Style.BRIGHT + k)
555 print(Style.RESET_ALL)
557 selected = arg.split()
560 print(
"Unknown workflow %s: skipping" % k)
563 print(
"%s %s" % (Fore.BLUE +
str(wfl.numId) + Fore.RESET,
564 Fore.GREEN + wfl.nameId + Fore.RESET))
565 print(
"%s contains %d workflows" % (Fore.RED + k + Fore.RESET, len(self.
matrices_[k].workFlows)))
571 print(Fore.RED + Style.BRIGHT +
"Wrong number of parameters passed")
572 print(Style.RESET_ALL)
574 workflow_class = args[0]
575 workflow_id = args[1]
576 passed_down_args = list()
578 passed_down_args = args[2:]
579 print(Fore.YELLOW + Style.BRIGHT +
"Running with the following options:\n")
580 print(Fore.GREEN + Style.BRIGHT +
"Workflow class: {}".
format(workflow_class))
581 print(Fore.GREEN + Style.BRIGHT +
"Workflow ID: {}".
format(workflow_id))
582 print(Fore.GREEN + Style.BRIGHT +
"Additional runTheMatrix options: {}".
format(passed_down_args))
583 print(Style.RESET_ALL)
585 print(Fore.RED + Style.BRIGHT +
"Unknown workflow selected: {}".
format(workflow_class))
586 print(
"Available workflows:")
588 print(Fore.RED + Style.BRIGHT + k)
589 print(Style.RESET_ALL)
591 wflnums = [x.numId
for x
in self.
matrices_[workflow_class].workFlows]
592 if float(workflow_id)
not in wflnums:
593 print(Fore.RED + Style.BRIGHT +
"Unknown workflow {}".
format(workflow_id))
594 print(Fore.GREEN + Style.BRIGHT)
596 print(Style.RESET_ALL)
600 if self.
processes_[workflow_id][0].poll()
is None:
601 print(Fore.RED + Style.BRIGHT +
"Workflow {} already running!".
format(workflow_id))
602 print(Style.RESET_ALL)
606 lognames = [
'stdout',
'stderr']
607 logfiles =
tuple(
'%s_%s_%s.log' % (workflow_class, workflow_id, name)
for name
in lognames)
608 stdout = open(logfiles[0],
'w')
609 stderr = open(logfiles[1],
'w')
610 command = (
'runTheMatrix.py',
'-w', workflow_class,
'-l', workflow_id)
611 if len(passed_down_args) > 0:
612 command +=
tuple(passed_down_args)
614 p = subprocess.Popen(command,
617 self.
processes_[workflow_id] = (p, time.time())
621 if text
and len(text) > 0:
622 return [t
for t
in self.
matrices_.
keys()
if t.startswith(text)]
627 print(
"\n".
join([
"runWorkflow workflow_class workflow_id\n",
628 "This command will launch a new and independent process that invokes",
630 "runTheMatrix.py -w workflow_class -l workflow_id [runTheMatrix.py options]",
631 "\nYou can specify just one workflow_class and workflow_id per invocation.",
632 "The job will continue even after quitting the interactive session.",
633 "stdout and stderr of the new process will be automatically",
634 "redirected to 2 logfiles whose names contain the workflow_class",
635 "and workflow_id. Mutiple command can be issued one after the other.",
636 "The working directory of the new process will be the directory",
637 "from which the interactive session has started.",
638 "Autocompletion is available for workflow_class, but",
639 "not for workflow_id. Supplying a wrong workflow_class or",
640 "a non-existing workflow_id for a valid workflow_class",
641 "will trigger an error and no process will be invoked.",
642 "The interactive shell will keep track of all active processes",
643 "and will prevent the accidental resubmission of an already",
647 print(Fore.GREEN + Style.BRIGHT +
"List of jobs:")
650 print(Fore.YELLOW + Style.BRIGHT +
"Active job: {} since {:.2f} seconds.".
format(w, time.time() - self.
processes_[w][1]))
652 print(Fore.RED + Style.BRIGHT +
"Done job: {}".
format(w))
653 print(Style.RESET_ALL)
656 print(
"\n".
join([
"Print a full list of active and done jobs submitted",
657 "in the ongoing interactive session"]))
660 print(
"\n".
join([
"searchInWorkflow wfl_name search_regexp\n",
661 "This command will search for a match within all workflows registered to wfl_name.",
662 "The search is done on both the workflow name and the names of steps registered to it."]))
665 if text
and len(text) > 0:
666 return [t
for t
in self.
matrices_.
keys()
if t.startswith(text)]
673 print(
"searchInWorkflow name regexp")
676 print(
"Unknown workflow")
681 pattern = re.compile(args[1])
683 print(
"Failed to compile regexp %s" % args[1])
686 for wfl
in self.
matrices_[args[0]].workFlows:
687 if re.match(pattern, wfl.nameId):
688 print(
"%s %s" % (Fore.BLUE +
str(wfl.numId) + Fore.RESET,
689 Fore.GREEN + wfl.nameId + Fore.RESET))
691 print(
"Found %s compatible workflows inside %s" % (Fore.RED +
str(counter) + Fore.RESET,
692 Fore.YELLOW +
str(args[0])) + Fore.RESET)
695 print(
"\n".
join([
"search search_regexp\n",
696 "This command will search for a match within all workflows registered.",
697 "The search is done on both the workflow name and the names of steps registered to it."]))
702 print(
"search regexp")
708 print(
"\n".
join([
"dumpWorkflowId [wfl-id1 [...]]\n",
709 "Dumps the details (cmsDriver commands for all steps) of the space-separated workflow-ids in input."]))
714 print(
"dumpWorkflowId [wfl-id1 [...]]")
722 for wfl
in mrd.workFlows:
723 if wfl.numId ==
float(wflid):
726 print(Fore.GREEN +
str(wfl.numId) + Fore.RESET +
" " + Fore.YELLOW + wfl.nameId + Fore.RESET)
727 for i,s
in enumerate(wfl.cmds):
728 print(fmt % (Fore.RED +
str(i+1) + Fore.RESET,
730 print(
"\nWorkflow found in %s." % key)
732 print(
"Workflow also found in %s." % key)
739 if opt.raw
and opt.show:
def performInjectionOptionTest(opt)
def do_predefined(self, arg)
def do_showWorkflow(self, arg)
def complete_showWorkflow(self, text, line, start_idx, end_idx)
def help_showWorkflow(self)
def help_dumpWorkflowId(self)
def complete_predefined(self, text, line, start_idx, end_idx)
def help_searchInWorkflow(self)
def do_dumpWorkflowId(self, arg)
void print(TMatrixD &m, const char *label=nullptr, bool mathematicaFormat=false)
def help_runWorkflow(self)
def help_predefined(self)
static std::string join(char **cmd)
def complete_searchInWorkflow(self, text, line, start_idx, end_idx)
def complete_runWorkflow(self, text, line, start_idx, end_idx)
def do_runWorkflow(self, arg)
def do_searchInWorkflow(self, arg)