Пример #1
0
 def __init__(self, suite, clock):
     typecheck('clock', clock, Clock)
     typecheck('suite', suite, Suite)
     self.__clock = copy.copy(clock)
     self.__suite = suite
     self.__nodes = collections.defaultdict(dict)
     self.__cycles = collections.defaultdict(OrderedDict)
Пример #2
0
 def node_size(self, rank_spec):
     typecheck('rank_spec', rank_spec, crow.sysenv.jobs.JobRankSpec)
     can_hyper = self.hyperthreading_allowed
     max_per_node = self.cores_per_node
     if can_hyper and rank_spec.get('hyperthreading', False):
         max_per_node *= self.cpus_per_core
     return max_per_node
Пример #3
0
 def __init__(self, child, locals, path=''):
     typecheck('child', child, Sequence)
     self.__child = list(child)
     self.__cache = list(child)
     self.__locals = locals
     self.__globals = {}
     self._path = path
Пример #4
0
def subdict_iter(d):
    typecheck('d', d, Mapping)
    dkeys = [k for k in d.keys()]
    vallist = [v for v in d.values()]
    piter = itertools.product(*vallist)
    dvalues = [p for p in piter]
    for j in range(len(dvalues)):
        yield dict([i for i in zip(dkeys, dvalues[j])])
Пример #5
0
 def __init__(self, child, path='', globals=None):
     #assert(not isinstance(child,dict_eval))
     typecheck('child', child, Mapping)
     self.__child = copy(child)
     self.__cache = copy(child)
     self.__globals = {} if globals is None else globals
     self.__is_validated = False
     self._path = path
Пример #6
0
def assume(tree,
           existing_cycles,
           current_cycle,
           assume_complete=None,
           assume_never_run=None):
    typecheck('tree', tree, LogicalDependency)
    if isinstance(tree, CycleExistsDependency):
        rel_cycle = tree.dt + current_cycle
        if rel_cycle in existing_cycles:
            return TRUE_DEPENDENCY
        return FALSE_DEPENDENCY
    elif isinstance(tree, TaskExistsDependency):
        cycle = current_cycle + tree.view.path[0]
        if assume_complete and assume_complete(tree.path) or \
           assume_never_run and assume_never_run(tree.path):
            return FALSE_DEPENDENCY
        alarm = tree.view.get_alarm(default=existing_cycles)
        if cycle in alarm:
            return TRUE_DEPENDENCY
        else:
            return FALSE_DEPENDENCY
    elif isinstance(tree, AndDependency):
        a = TRUE_DEPENDENCY
        for d in tree:
            a = a & assume(d, existing_cycles, current_cycle, assume_complete,
                           assume_never_run)
        return a
    elif isinstance(tree, OrDependency):
        a = FALSE_DEPENDENCY
        for d in tree:
            a = a | assume(d, existing_cycles, current_cycle, assume_complete,
                           assume_never_run)
        return a
    elif isinstance(tree, NotDependency):
        return ~assume(tree.depend, existing_cycles, current_cycle,
                       assume_complete, assume_never_run)
    elif isinstance(tree, StateDependency):
        if assume_never_run and assume_never_run(tree.path):
            return FALSE_DEPENDENCY
        if assume_complete and assume_complete(tree.path):
            return TRUE_DEPENDENCY if tree.state==COMPLETED \
              else FALSE_DEPENDENCY
        if current_cycle + tree.path[0] not in existing_cycles:
            # Prior cycle tasks will never complete, run, or fail.
            return FALSE_DEPENDENCY
        return tree
    elif isinstance(tree, EventDependency):
        if assume_never_run and assume_never_run(tree.event.parent.path):
            return FALSE_DEPENDENCY
        if assume_complete and assume_complete(tree.event.parent.path):
            return FALSE_DEPENDENCY
        if current_cycle + tree.path[0] not in existing_cycles:
            # Prior cycle events will never be set.
            return FALSE_DEPENDENCY
        return tree

    return tree
Пример #7
0
def convert_event_dep(fd,task,dep_path,event_name,clock,time_format,negate,undated):
    assert(isinstance(undated,OrderedDict))
    typecheck('clock',clock,crow.tools.Clock)
    task_path,did_undated=undate_path(clock.now,time_format,task.path,undated)
    dep_path,did_undated=undate_path(clock.now,time_format,dep_path,undated)
    rel_path=relative_path(task_path,dep_path)
    if did_undated and rel_path[0]=='/':
        undated[rel_path]=1
    fd.write(f'{rel_path}:{event_name}{" is clear" if negate else ""}')
Пример #8
0
 def __init__(self, view, state):
     if state not in [COMPLETED, RUNNING, FAILED]:
         raise TypeError('Invalid state.  Must be one of the constants '
                         'COMPLETED, RUNNING, or FAILED')
     typecheck('view', view, SuiteView)
     if isinstance(view, SlotView):
         raise NotImplementedError('Data dependencies are not implemented')
     self.view = view
     self.state = state
Пример #9
0
def convert_state_dep(fd,task,dep,clock,time_format,negate,undated):
    assert(isinstance(undated,OrderedDict))
    typecheck('clock',clock,crow.tools.Clock)
    task_path,did_undated=undate_path(clock.now,time_format,task.path,undated)
    dep_path,did_undated=undate_path(clock.now,time_format,dep.view.path,undated)
    rel_path=relative_path(task_path,dep_path)
    if did_undated and rel_path[0]=='/':
        undated[rel_path]=1
    state=ECFLOW_STATE_MAP[dep.state]
    fd.write(f'{rel_path} {"!=" if negate else "=="} {state}')
Пример #10
0
 def _rocotoify_dep(self, dep, defining_path):
     typecheck('dep', dep, LogicalDependency)
     try:
         if dep in self.__rocotoified:
             return self.__rocotoified[dep]
         roco = self._rocotoify_dep_impl(dep, defining_path)
         self.__rocotoified[dep] = roco
         return roco
     except RecursionError as re:
         raise SelfReferentialDependency(
             f'/{"/".join([str(d) for d in defining_path[1:]])}: '
             'cyclic dependency graph referenced from this task.')
Пример #11
0
 def representer(dumper,data):
     assert('up' not in data)
     typecheck('data',data,Mapping)
     raw_data=data._raw_child()
     typecheck('data._raw_child()',raw_data,Mapping)
     try:
         if key is None:
             return dumper.represent_data(raw_data)
         else:
             return dumper.represent_mapping(key,raw_data)
     except(IndexError,TypeError,ValueError) as e:
         _logger.error(f'{data._path}: cannot represent: {e} (key={key})')
         raise
Пример #12
0
 def __init__(self, view, cycle):
     self.view = view
     self.trigger = TRUE_DEPENDENCY
     self.complete = FALSE_DEPENDENCY
     self.time = ZERO_DT
     self.cycle = cycle
     self.alarm = view.get_alarm()
     self.trigger = view.get_trigger_dep().copy_dependencies()
     self.complete = view.get_complete_dep().copy_dependencies()
     if 'Time' in view and view.Time is not None:
         typecheck('Time', view.Time, datetime.timedelta)
         self.time = copy.copy(view.Time)
     self.children = collections.OrderedDict()
Пример #13
0
 def remove_undefined_tasks(self, tree):
     typecheck('tree', tree, LogicalDependency)
     # NOTE: Do not remove event dependencies for undefined tasks.
     # They are critical to allow ecflow to use a task that waits
     # for data and sets an event while rocoto uses a data event
     # with no task.
     if isinstance(tree, StateDependency):
         # Node is not defined, so assume it is complete
         dep_path = SuitePath([_ZERO_DT] + tree.view.path[1:])
         if dep_path not in self.__all_defined:
             tree = TRUE_DEPENDENCY
     elif isinstance(tree, NotDependency):
         tree = ~self.remove_undefined_tasks(tree.depend)
     elif isinstance(tree, AndDependency) or isinstance(tree, OrDependency):
         deplist = [self.remove_undefined_tasks(t) for t in tree]
         tree = type(tree)(*deplist)
     return tree
Пример #14
0
    def omp_threads_for(self, rank_spec):
        typecheck('rank_spec', rank_spec, crow.sysenv.jobs.JobRankSpec)
        omp_threads = max(1, rank_spec.get('OMP_NUM_THREADS', 1))

        #        print('omp_thread = ',omp_threads)
        if omp_threads != MAXIMUM_THREADS:
            return omp_threads

        can_hyper = self.hyperthreading_allowed
        max_threads_per_node = self.cores_per_node
        if can_hyper and rank_spec.get('hyperthreads', False):
            max_threads_per_node *= max(
                1, min(self.cpus_per_core, rank_spec.hyperthreads))

        result = max_threads_per_node // self.max_ranks_per_node(rank_spec)
        #        print('max_threads_per_node = ', max_threads_per_node)
        #        print('self.max_ranks_per_node(rank_spec) = ',self.max_ranks_per_node(rank_spec))
        return result
Пример #15
0
    def omp_threads_for(self, rank_spec):
        typecheck('rank_spec', rank_spec, crow.sysenv.jobs.JobRankSpec)
        omp_threads = max(1, rank_spec.get('OMP_NUM_THREADS', 1))
        if omp_threads != MAXIMUM_THREADS:
            return omp_threads

        can_hyper = self.hyperthreading_allowed
        max_ranks_per_node = self.cores_per_node
        if can_hyper and rank_spec.get('hyperthreading', False):
            max_ranks_per_node *= self.cpus_per_core
        if rank_spec.is_mpi():
            ppn = max_ranks_per_node
        else:
            ppn = 1

        max_ppn = rank_spec.get('max_ppn', 0)
        if max_ppn:
            ppn = min(max_ppn, ppn)

        return max_ranks_per_node // ppn
Пример #16
0
 def assume(self, clock, assume_complete=None, assume_never_run=None):
     trigger0 = self.trigger
     complete0 = self.complete
     typecheck('self.alarm', self.alarm, Clock)
     if self.cycle not in self.alarm:
         self.trigger = FALSE_DEPENDENCY
         self.complete = FALSE_DEPENDENCY
     elif self.view.get('Disable', False):
         self.trigger = FALSE_DEPENDENCY
         self.complete = FALSE_DEPENDENCY
     else:
         self.trigger = algebra_simplify(
             algebra_assume(self.trigger, clock, self.cycle,
                            assume_complete, assume_never_run))
         self.complete = algebra_simplify(
             algebra_assume(self.complete, clock, self.cycle,
                            assume_complete, assume_never_run))
     if trigger0 != self.trigger or complete0 != self.complete:
         return True
     return False
Пример #17
0
 def _duplicate(self, parent, dimensions, dimval, dimidx):
     child_dimensions = dimensions
     if 'Foreach' in self:
         typecheck(f'{self._path}.Foreach', self.Foreach, Sequence,
                   'sequence')
         d2 = dict()
         for idxname in self.Foreach:
             if idxname in dimensions:
                 d2[idxname] = dimensions[idxname]
             else:
                 raise KeyError(
                     f'{self._path}.Foreach: {idxname}: no such dimension')
         dimensions = d2
     dict_iter = [{}]
     if dimensions:
         dimensions_to_dimidx = dict()
         for k, v in dimensions.items():
             dimensions_to_dimidx[k] = [n for n in range(len(v))]
         dict_iter = subdict_iter(dimensions_to_dimidx)
     for more_dimidx in dict_iter:
         child_dimidx = copy(dimidx)
         child_dimidx.update(more_dimidx)
         child_dimval = dict()
         for i_dimname, i_dimidx in child_dimidx.items():
             child_dimval[i_dimname] = dimensions[i_dimname][i_dimidx]
         cls = ARRAY_ELEMENT_TYPE_MAP[type(self)]
         t = cls(self._raw_child(), globals=self._globals())
         t._path = self._path  # used if Name is missing
         t['dimlist'] = dict_eval(dimensions)
         t['dimval'] = dict_eval(child_dimval)
         t['dimidx'] = dict_eval(child_dimidx)
         name = t.Name
         t._path = f'{parent._path}.{name}'
         for k, v in self._raw_child().items():
             if hasattr(v, '_duplicate'):
                 for name2, content2 in v._duplicate(
                         t, child_dimensions, dimval, dimidx):
                     t[name2] = content2
         yield name, t
Пример #18
0
    def max_ranks_per_node(self, rank_spec):
        typecheck('rank_spec',
                  rank_spec,
                  crow.sysenv.jobs.JobRankSpec,
                  print_contents=True)
        can_hyper = self.hyperthreading_allowed
        max_per_node = self.cores_per_node
        max_threads_per_node = self.cores_per_node

        if can_hyper and rank_spec.get('hyperthreads', False):
            max_threads_per_node *= max(
                1, min(self.cpus_per_core, rank_spec.hyperthreads))
            max_per_node *= max(
                1, min(self.cpus_per_core, rank_spec.hyperthreads))

        threads_per_node = max_per_node
        omp_threads = max(1, rank_spec.get('OMP_NUM_THREADS', 1))

        if omp_threads != MAXIMUM_THREADS:
            max_per_node //= omp_threads
        elif rank_spec.mpi_ranks < 2:
            # Special case: maximum threads with non-MPI job, so return 1
            return 1

        max_ppn = rank_spec.get('max_ppn', 0)
        if max_ppn:
            max_per_node = min(max_ppn, max_per_node)

        if self.memory_per_node:
            max_per_node = int(
                min(max_per_node,
                    self.memory_per_node / rank_spec.memory_per_rank))

        if max_per_node < 1:
            raise MachineTooSmallError(
                f'Specification too large for node: max threads {threads_per_node} for {rank_spec!r} in partition with {self.cores_per_node} cores per node{"" if not self.memory_per_node else ("and "+str(self.memory_per_node)+" MB of RAM per node")}.'
            )

        return max_per_node
Пример #19
0
def from_suite(suite, filename):
    typecheck('suite', suite, Suite)
    typecheck('filename', filename, str)
    df = Dataflow(filename)

    # First pass: add output slots:
    for actor, slot, sdata in _walk_task_tree_for(suite, ConfigOutputSlot):
        loc, meta = _parse_slot(actor, slot, sdata, 'O')
        df.add_output_slot(actor, slot, loc, meta)

    # Second pass: add input slots:
    for actor, slot, sdata in _walk_task_tree_for(suite, ConfigInputSlot):
        meta = _parse_slot(actor, slot, sdata, 'I')
        _logger.debug(f'{actor}.{slot}: add input slot with meta {meta}')
        df.add_input_slot(actor, slot, meta)

        for ometa in meta_expand_iter(meta):
            _logger.debug(f'{actor}.{slot}: will check meta {ometa}')

        for ometa in meta_expand_iter(meta):
            _logger.debug(f"{actor}.{slot}: check input slot meta {ometa}")
            odata = sdata.get_output_slot(ometa)

            oslot = None
            for oslot in df.find_output_slot(odata.get_actor_path(),
                                             odata.get_slot_name(), ometa):
                break

            islot = None
            for islot in df.find_input_slot(actor, slot, ometa):
                break
            assert (islot)
            if not oslot:
                raise ValueError(f'{actor}.{slot} output refers to '
                                 'invalid or missing output slot.')
            _logger.debug(f"{islot}: connect to {oslot}")
            islot.connect_to(oslot)
    return df
Пример #20
0
    def max_ranks_per_node(self, rank_spec):
        typecheck('rank_spec',
                  rank_spec,
                  crow.sysenv.jobs.JobRankSpec,
                  print_contents=True)
        can_hyper = self.hyperthreading_allowed
        max_per_node = self.cores_per_node
        if can_hyper and rank_spec.get('hyperthreading', False):
            max_per_node *= self.cpus_per_core
        threads_per_node = max_per_node
        omp_threads = max(1, rank_spec.get('OMP_NUM_THREADS', 1))

        if omp_threads != MAXIMUM_THREADS:
            max_per_node //= omp_threads

        max_ppn = rank_spec.get('max_ppn', 0)
        if max_ppn:
            max_per_node = min(max_ppn, max_per_node)

        if max_per_node < 1:
            raise MachineTooSmallError(
                f'Specification too large for node: max {threads_per_node} for {rank_spec!r}'
            )
        return max_per_node
Пример #21
0
 def __init__(self, event):
     typecheck('event', event, EventView)
     self.event = event
Пример #22
0
def command_without_exe(parallelism, jobspec, exe):
    typecheck('jobspec', jobspec, crow.sysenv.JobResourceSpec)
    shell_command_obj = parallelism.make_ShellCommand(jobspec)
    cmd = list(shell_command_obj.command)
    return ' '.join([s for s in cmd if s != exe])
Пример #23
0
def to_ecflow(suite):
    typecheck('suite',suite,Suite)
    return ToEcflow(suite).to_ecflow()
Пример #24
0
def to_ecflow(suite,apply_overrides=True):
    typecheck('suite',suite,Suite)
    return ToEcflow(suite,apply_overrides=apply_overrides).to_ecflow()
Пример #25
0
 def __init__(self, *args):
     if not args: raise ValueError('Tried to create an empty OrDependency')
     self.depends = list(args)
     for dep in self.depends:
         typecheck('A dependency', dep, LogicalDependency)
Пример #26
0
 def add_ecf_file(self,ecf_file_set_name,path_string,ecf_file_contents):
     typecheck('ecf_file_set_name',ecf_file_set_name,str)
     typecheck('path_string',path_string,str)
     typecheck('ecf_file_contents',ecf_file_contents,str)
     self.ecf_files[ecf_file_set_name][path_string]=ecf_file_contents
     assert(self.have_ecf_file(ecf_file_set_name,path_string))
Пример #27
0
    def _make_suite_def(self,cycle):
        self._select_cycle(cycle)
        clock=self.suite.Clock

        suite_name_format=self.suite.ecFlow.suite_name
        suite_name=cycle.strftime(suite_name_format)
        undated=OrderedDict()
        sio=StringIO()

        if 'before_suite_def' in self.suite:
            sio.write(self.suite.before_suite_def)
            sio.write('\n')

        sio.write(f'suite {suite_name}\n')
        if 'ecflow_def' in self.suite:
            for line in self.suite.ecflow_def.splitlines():
                sio.write(f'{self.indent}{line.rstrip()}\n')

        ECF_FILES=self.suite.ecf_file_set.ECF_FILES
        sio.write(f"{self.indent}edit ECF_FILES '{ECF_FILES}'\n")

        def exit_fun(node):
            if node.is_family():
                indent=max(0,len(node.path)-1)*self.indent
                ended=f'/{suite_name}/{node.view.task_path_str}'
                ended=re.sub('/+','/',ended)
                sio.write(f'{indent}endfamily # {ended}\n')

        for node in self._walk_job_graph(cycle,skip_fun=skip_fun,exit_fun=exit_fun):
            indent0=max(0,len(node.path)-1)*self.indent
            indent1=max(0,len(node.path))*self.indent
            nodetype='task' if node.is_task() else 'family'
            sio.write(f'{indent0}{nodetype} {node.path[-1]}')
            if node.is_family():
                started=f' # /{suite_name}/{node.view.task_path_str}'
                started=re.sub('/+','/',started)
                sio.write(started)
                if 'ecf_file_set' in node.view:
                    ECF_FILES=node.view.ecf_file_set.ECF_FILES
                    sio.write(f"\n{self.indent}edit ECF_FILES '{ECF_FILES}'")

            sio.write('\n')

            if 'ecflow_def' in node.view:
                for line in node.view.ecflow_def.splitlines():
                    sio.write(f'{indent1}{line.rstrip()}\n')

            if 'Dummy' in node.view and node.view.Dummy:
                sio.write(f"{indent1}edit ECF_DUMMY_TASK ''\n")
                sio.write(f"{indent1}defstatus complete\n")

            if node.trigger not in [FALSE_DEPENDENCY,TRUE_DEPENDENCY]:
                sio.write(f'{indent1}trigger ')
                dep_to_ecflow(sio,node,node.trigger,clock,suite_name_format,undated)
                sio.write('\n')
            if node.complete not in [FALSE_DEPENDENCY,TRUE_DEPENDENCY]:
                sio.write(f'{indent1}complete ')
                dep_to_ecflow(sio,node,node.complete,clock,suite_name_format,undated)
                sio.write('\n')
            if node.time>ZERO_DT:
                when=cycle+node.time
                ectime=when.strftime('%H:%M')
                sio.write(f'{indent1}time {ectime}\n')
                if self.settings.dates_in_time_dependencies:
                    ecdate=when.strftime('%d.%m.%Y')
                    sio.write(f'{indent1}date {ecdate}\n')

            event_number=node.view.get('ecflow_first_event_number',1)
            typecheck(f'{node.view.task_path_var}.ecflow_first_event_number',event_number,int)
            if node.is_task():
                for item in node.view.child_iter():
                    if item.is_event():
                        sio.write(f'{indent1}event {event_number} '
                                  f'{item.path[-1]}\n')
                    event_number+=1

        sio.write(f'endsuite # /{suite_name}\n')
        suite_def_without_externs=sio.getvalue()
        sio.close()
        sio=StringIO()
        if undated:
            for d in undated.keys():
                sio.write(f'extern {d}\n')
            sio.write(suite_def_without_externs)
            suite_def=sio.getvalue()
            sio.close()
        else:
            suite_def=suite_def_without_externs
        return suite_name, suite_def
Пример #28
0
 def __init__(self, depend):
     typecheck('A dependency', depend, LogicalDependency)
     self.depend = depend
Пример #29
0
 def __init__(self, view):
     typecheck('view', view, TaskableView, 'Task or Tamily')
     self.view = view
Пример #30
0
def to_rocoto(suite, apply_overrides=True):
    typecheck('suite', suite, Suite)
    return ToRocoto(suite,
                    apply_overrides=apply_overrides)._expand_workflow_xml()