Пример #1
0
    def check(self, checker):

        for place, number in utils.multiset(
            [edge.place for edge in self.edges_in]).items():
            if number != 1:
                raise utils.PtpException(
                    "There can be at most one input edge "
                    "between place and transition", self.get_source())

        if self.collective:
            inscriptions = [
                inscription for edge in self.edges_out
                for inscription in edge.inscriptions
                if inscription.is_collective()
            ]
            if len(inscriptions) > 1:
                raise utils.PtpException(
                    "At most one collective inscription may be defined",
                    inscriptions[-1].source)
            if inscriptions:
                op = inscriptions[0].get_collective_operation()
                need_root = op == "scatter" or op == "gather" or op == "bcast"
                if not self.root and need_root:
                    raise utils.PtpException("Root not defined",
                                             self.get_source())
            else:
                need_root = False

            if not need_root and self.root:
                raise utils.PtpException(
                    "Root cannot be defined for this operation",
                    self.get_source())

        for edge in self.edges_in:
            edge.check_edge_in(checker)

        for edge in self.edges_out:
            edge.check_edge_out(checker)

        if self.guard:
            checker.check_expression(self.guard, self.get_input_decls(),
                                     "bool", self.get_source("guard"))
        if self.time_substitution:
            decls = self.get_decls()
            decls.set("ctx", "casr::Context", force=True)
            decls.set("transitionTime",
                      "ca::IntTime",
                      self.get_source(),
                      force=True)
            checker.check_expression(self.time_substitution, decls,
                                     "ca::IntTime", self.get_source())
        if self.clock_substitution:
            decls = self.get_decls()
            decls.set("ctx", "casr::Context", force=True)
            decls.set("clockTime",
                      "ca::IntTime",
                      self.get_source(),
                      force=True)
            checker.check_expression(self.clock_substitution, decls,
                                     "ca::IntTime", self.get_source())
Пример #2
0
    def check_edge_out(self, checker):
        if not self.expr:
            raise utils.PtpException(
                "Main expression of output inscription is empty", self.source)

        if self.edge.transition.collective and self.target is not None:
            raise utils.PtpException(
                "Output edges of collective transitions cannot contain '@'",
                self.source)

        allowed = ["bulk", "multicast", "if", "seq"]

        if self.edge.transition.collective:
            if self.edge.transition.root:
                allowed.append("root")
            allowed += ["scatter", "gather", "allgather", "bcast"]
        self.check_config(allowed)

        if self.check_config_with_expression("if"):
            decls = self.edge.transition.get_input_decls_with_size(self.source)
            checker.check_expression(self.config["if"], decls, "bool",
                                     self.source)

        if self.check_config_with_expression("seq"):
            if not utils.is_integer(self.config["seq"]):
                raise utils.PtpException(
                    "Parameter of 'seq' has to be a constant integer",
                    self.source)
            self.config["seq"] = int(self.config["seq"])

        if self.target is not None:
            checker.check_expression(self.target,
                                     self.edge.transition.get_decls(),
                                     self.target_type, self.source)
        self.check(checker)
Пример #3
0
 def check_config_with_expression(self, name, variable=False):
     if name in self.config:
         if self.config[name] is None:
             raise utils.PtpException(
                 "'{0}' requires an expression".format(name), self.source)
         if variable and \
             not self.edge.transition.net.project.is_expr_variable(self.config[name]):
             raise utils.PtpException(
                 "'{0}' requires an variable".format(name))
         return True
     else:
         return False
Пример #4
0
 def set(self, var, t, source=None, force=False):
     if not force and var in self.types:
         if self.types[var] != t:
             if source is None:
                 source = self.source
             msg = "Invalid type of variable '{0}' ({1}/{2})".format(
                 var, self.types[var], t)
             raise utils.PtpException(msg, source)
     else:
         self.types[var] = t
Пример #5
0
    def check_edge_in(self, checker):
        self.check(checker)

        for inscription in self.inscriptions:
            inscription.check_edge_in(checker)

        if self.size_substitution:
            raise utils.PtpException(
                "Size substition can be used only for output edges",
                self.source)
Пример #6
0
    def check_edge_in(self, checker):
        if self.target is not None:
            raise utils.PtpException("Input edges cannot contain '@'",
                                     self.source)

        allowed = [
            "bulk", "guard", "svar", "filter", "from", "if", "sort_by_source"
        ]
        if self.edge.transition.collective and self.edge.transition.root:
            allowed.append("root")

        self.check_config(allowed)

        if self.check_config_with_expression("svar", variable=True):
            decls = self.edge.transition.get_input_decls()
            checker.check_expression(self.config["svar"], decls,
                                     self.get_svar_type(), self.source)

        if self.check_config_with_expression("filter"):
            decls = self.edge.transition.get_input_decls()
            checker.check_expression(self.config["filter"], decls, "bool",
                                     self.source)

        if self.check_config_with_expression("from"):
            decls = self.edge.transition.get_input_decls()
            checker.check_expression(self.config["from"], decls, "int",
                                     self.source)

        if self.check_config_with_expression("guard"):
            decls = self.edge.transition.get_input_decls_with_size(self.source)
            checker.check_expression(self.config["guard"], decls, "bool",
                                     self.source)

        if self.check_config_with_expression("if"):
            decls = self.edge.transition.get_input_decls_with_size(self.source)
            checker.check_expression(self.config["if"], decls, "bool",
                                     self.source)
        self.check(checker)

        if "sort_by_source" in self.config and "bulk" not in self.config:
            raise utils.PtpException("Configuration option 'sort_by_source' "
                                     "can be used only with 'bulk'")
Пример #7
0
    def check(self, checker):
        for place in self.places:
            place.check(checker)

        for transition in self.transitions:
            transition.check(checker)

        for area in self.areas:
            area.check(checker)

        place = utils.check_uniquness(self.get_input_places(),
                                      lambda p: p.interface_input)
        if place is not None:
            raise utils.PtpException("Input iterfaces have not unique names",
                                     place.get_source("type"))

        place = utils.check_uniquness(self.get_output_places(),
                                      lambda p: p.interface_output)
        if place is not None:
            raise utils.PtpException("Output iterfaces have not unique names",
                                     place.get_source("type"))
Пример #8
0
 def check(self, checker):
     if self.has_expr():
         op = self.get_collective_operation()
         if op == "scatter":
             checker.check_expression(self.expr,
                                      self.edge.transition.get_decls(),
                                      get_container_type(self.type),
                                      self.source)
         elif op == "gather" or op == "allgather":
             t = self.edge.transition.net.project.parse_typename(
                 self.type, self.source)
             if len(t) < 2 or len(t[1]) < 0 or t[0] != "std::vector":
                 raise utils.PtpException("Invalid type of expression",
                                          self.source)
             typename = t[1][0]
             checker.check_expression(self.expr,
                                      self.edge.transition.get_decls(),
                                      typename, self.source)
         else:
             checker.check_expression(self.expr,
                                      self.edge.transition.get_decls(),
                                      self.type, self.source)
Пример #9
0
def analyze_transition(tr):
    variable_sources = {
    }  # string -> uid - which inscriptions carry input variables
    reuse_tokens = {
    }  # uid -> uid - identification number of token for output inscpription
    fresh_tokens = []  # (uid, type) - what tokens has to be created for output
    used_tokens = [
    ]  # [uid] - Tokens from input inscriptions that are reused on output
    variable_sources_out = {}  # string -> uid or None
    bulk_overtake = []  # [uid]
    overtaken_variables = set()

    def inscription_out_weight(inscription):
        # Reorder edges, bulk edges first because we want them send first
        # Otherwise it can cause problems like in sending results in "workers" example
        s = inscription.config.get("seq")
        if s is None:
            seq = 0
        else:
            seq = int(s) * 3
        if inscription.is_bulk():
            return seq
        # Unconditional edges has higher priority
        if inscription.is_conditioned():
            return seq + 2
        else:
            return seq + 1

    def inscription_in_weight(inscription):
        if inscription.is_conditioned():
            return 1
        else:
            return 0

    inscriptions_in = sum((edge.inscriptions for edge in tr.edges_in), [])
    inscriptions_in.sort(key=inscription_in_weight)
    inscriptions_out = sum((edge.inscriptions for edge in tr.edges_out), [])
    inscriptions_out.sort(key=inscription_out_weight)

    variable_sources = get_variable_sources(inscriptions_in)
    # Order input inscriptions by variable dependancy
    inscriptions_in = utils.topological_ordering(inscriptions_in, is_dependant)
    if inscriptions_in is None:
        raise utils.PtpException("Circle variable dependancy", tr.get_source())

    # Try reuse tokens
    for inscription in inscriptions_out:
        if inscription.is_bulk() or not inscription.is_local():
            continue  # Bulk and nonlocal edge cannot use token reusage
        if not inscription.is_expr_variable():
            continue  # Current implementation reuses tokens only for variable expression
        if inscription.is_collective():
            continue  # Collective operations cannot use token reusage
        token_uid = variable_sources.get(inscription.expr)
        if token_uid is None or token_uid in used_tokens:
            # Variable is not taken from input as token
            # or token is already reused --> reusage not possible
            continue

        reuse_tokens[inscription.uid] = token_uid
        used_tokens.append(token_uid)

    # Setup fresh variables where token was not reused
    for inscription in inscriptions_out:
        if not inscription.is_expr_variable():
            continue  # We are interested only in variables
        variable = inscription.expr
        if variable in variable_sources:
            # Variable take from input so we do not have to deal here with it
            continue
        if variable in variable_sources_out:
            # Variable already prepared for output
            continue
        if inscription.is_bulk():
            # No token, just build variable
            variable_sources_out[variable] = None
            continue
        if inscription.is_local():
            # Local send, we prepare token
            fresh_tokens.append((inscription.uid, inscription.edge.place.type))
            variable_sources_out[variable] = inscription.uid
            reuse_tokens[
                inscription.uid] = inscription.uid  # Use this fresh new token
        else:
            # Just create variable
            variable_sources_out[variable] = None

    for inscription in reversed(inscriptions_out):
        # Now we are checking overtake. It has to be in reversed order
        # becacase overtake has to be the last operation on variable
        if not inscription.is_bulk() or not inscription.is_expr_variable():
            continue  # We are interested only in variables and bulk inscriptions
        if inscription.expr not in overtaken_variables:
            overtaken_variables.add(inscription.expr)
            bulk_overtake.append(inscription.uid)

    for inscription in inscriptions_out:
        for variable in inscription.get_other_variables():
            if variable not in variable_sources and \
               variable not in variable_sources_out:
                variable_sources_out[variable] = None

    tr.inscriptions_in = inscriptions_in
    tr.inscriptions_out = inscriptions_out
    tr.variable_sources = variable_sources
    tr.reuse_tokens = reuse_tokens
    tr.variable_sources_out = variable_sources_out
    tr.fresh_tokens = fresh_tokens
    tr.bulk_overtake = bulk_overtake
Пример #10
0
    def check(self, checker):
        bulk = any(inscription.is_bulk() for inscription in self.inscriptions)

        if bulk and len(self.inscriptions) > 1:
            raise utils.PtpException(
                "Bulk inscription cannot be combined with others", self.source)
Пример #11
0
 def check_config(self, valid_keys):
     invalid_key = utils.key_not_in_list(self.config, valid_keys)
     if invalid_key is not None:
         raise utils.PtpException(
             "Invalid config item '{0}'".format(invalid_key), self.source)