def test_map_to_core(graph, platform): cfs = StaticCFS(platform) for core in platform.processors(): for proc in graph.processes(): mapping = Mapping(graph, platform) cfs.map_to_core(mapping, proc, core) assert mapping._process_info[proc.name].affinity == core
def form_mappings(self): """Form mappings from the parsed data. Returns the list of tuples, the first element of the tuple is the `Mapping` object, the next elements are the attribute values in the order of `attributes` paramater. """ if self.mappings is not None: log.warning("Mappings were already generated, returning them.") return self.mappings time_col = self._metadata_exec_time energy_col = self._metadata_energy self.mappings = [] for entry in self._data: from_list = [] for process in self._process_names: pe = self._processor_numbers[entry[process]] from_list.append(pe) if from_list != []: mapping = self.mapper.generate_mapping(from_list) # Update energy-utility metadata if time_col is not None: mapping.metadata.exec_time = float(entry[time_col]) if energy_col is not None: mapping.metadata.energy = float(entry[energy_col]) else: mapping = Mapping(self.graph, self.platform) self.mappings.append( (mapping,) + tuple(entry[p] for p in self._attributes) ) return self.mappings
def generate_mappings(self, graphs, traces, load=None, restricted=None): if len(graphs) == 0: return [] else: log.info(f"generating fair mapping for {len(graphs)} apps") comMapGen = {} if len(traces) != len(graphs): raise RuntimeError( f"Mapper received unbalanced number of traces ({len(traces)}) and applications ({len(graphs)})" ) for graph in graphs: randMapGen = RandomPartialMapper(graph, self.platform) comMapGen[graph] = ComPartialMapper(graph, self.platform, randMapGen) trace_summaries = {} mappings = {} for graph, trace in zip(graphs, traces): trace_summaries.update( gen_trace_summary(graph, self.platform, trace)) mappings[graph] = Mapping(graph, self.platform) mapping_dict = self.generate_mapping_dict(graphs, trace_summaries, load=load, restricted=restricted) for graph in graphs: for proc in graph.processes(): self.map_to_core(mappings[graph], proc, mapping_dict[proc]) res = [] for graph in mappings: res.append(comMapGen[graph].generate_mapping(mappings[graph])) return res
def generate_mapping(self, part_mapping=None): # configure policy of schedulers if part_mapping is None: part_mapping = Mapping(self.graph, self.platform) return ComPartialMapper.generate_mapping_static( self.graph, self.platform, part_mapping=part_mapping )
def completeMappingAtRandom(self, processMappingVector): # create empty mapping, complete it with generated process mapping # and random channel mapping mapping = Mapping(self.__graph, self.__platform) mapping.from_list(processMappingVector) assert mapping.get_unmapped_channels() == [] assert mapping.get_unmapped_processes() == [] return mapping
def generate_mapping(self, load=None, restricted=None): trace_summary = gen_trace_summary(self.graph, self.platform, self.trace) mapping = Mapping(self.graph, self.platform) mapping_dict = self.generate_mapping_dict([self.graph], trace_summary, load=load, restricted=restricted) for proc in self.graph.processes(): self.map_to_core(mapping, proc, mapping_dict[proc]) return self.comMapGen.generate_mapping(mapping)
def generate_pe_mapping_from_simple_vector( vec, graph, platform, vec_pe_mapping, vec_cp_mapping ): mapping = Mapping(graph, platform) # map processes to scheduler and processor for i, p in enumerate( sorted(graph.processes(), key=(lambda pr: pr.name)) ): # choose the desired processor from list pe = vec_pe_mapping[vec[i]] # choose the first scheduler from list scheduler = platform.find_scheduler_for_processor(pe) # set the affinity of the scheduler to the choosen PE affinity = pe # always set priority to 0 priority = 0 info = ProcessMappingInfo(scheduler, affinity, priority) # configure mapping mapping.add_process_info(p, info) if len(vec) > len(graph.processes()): if len(vec) != (len(graph.processes()) + len(graph.channels())): log.error( f"Invalid mapping vector size. " f"Should be {len(graph.processes())}" f" or {len(graph.processes()) + len(graph.channels())}" ) raise RuntimeError n = len(graph.processes()) for j, c in enumerate( sorted(graph.channels(), key=(lambda ch: ch.name)) ): i = j + n primitive = vec_cp_mapping[vec[i]] capacity = 16 # fixed channel bound this may cause problems info = ChannelMappingInfo(primitive, capacity) mapping.add_channel_info(c, info) log.debug( "com_map: map channel %s to the primitive %s and bound to %d " "tokens" % (c.name, primitive.name, capacity) ) return mapping
def generate_mapping_static(graph, platform, part_mapping=None): """Generates an partial mapping from a given partial mapping The generated mapping provides a best effort placement of communication structures. The rest is deterministically chosen to the first available option. :param mapping: a partial mapping with placed processes or an empty mapping :type mapping: mapping :raises: RuntimeError if the algorithm is not able to find a suitable channel mapping for a process mapping (for partial mappings with incomplete process mappings). """ # generate new mapping if no partial mapping is given if not part_mapping: part_mapping = Mapping(graph, platform) # map processes to scheduler and processor if not already done processes = part_mapping.get_unmapped_processes() for p in processes: scheduler = list(platform.schedulers())[0] affinity = scheduler.processors[0] priority = 0 info = ProcessMappingInfo(scheduler, affinity, priority) part_mapping.add_process_info(p, info) log.debug( "com_map: map process %s to scheduler %s and processor %s " "(priority: %d)", p.name, scheduler.name, affinity.name, priority, ) # map communication primitives channels = part_mapping.get_unmapped_channels() for c in channels: capacity = 16 # fixed channel bound this may cause problems suitable_primitives = [] src = part_mapping.process_info(c.source).affinity sinks = [part_mapping.process_info(s).affinity for s in c.sinks] for p in part_mapping.platform.primitives(): if p.is_suitable(src, sinks): suitable_primitives.append(p) if len(suitable_primitives) == 0: raise RuntimeError( "com_map: Mapping failed! No suitable primitive for " "communication from %s to %s found!" % (src.name, str(sinks)) ) primitive = ComPartialMapper._get_minimal_costs( suitable_primitives, c, src, sinks ) info = ChannelMappingInfo(primitive, capacity) part_mapping.add_channel_info(c, info) log.debug( "com_map: map channel %s to the primitive %s and bound to %d " "tokens" % (c.name, primitive.name, capacity) ) return part_mapping
def generate_mapping(self, part_mapping=None): """Generate a random mapping. The generated mapping takes a partial mapping (that may also be empty) as starting point. All open mapping decissions were taken by generated randomness derived from the given seed. :param seed: initial seed for the random generator :type seed: integer :param part_mapping: partial mapping to start from :type part_mapping: Mapping """ # generate new mapping if no partial mapping is given if not part_mapping: part_mapping = Mapping(self.graph, self.platform) # check if the platform/graph is equivalent if (part_mapping.platform is not self.platform or part_mapping.graph is not self.graph): raise RuntimeError( "rand_map: Try to map partial mapping of platform,dataflow " f"{part_mapping.platform.name},{part_mapping.graph.name} to " f"{self.platform.name},{self.graph.name}", ) available_processors = list(self.platform.processors()) if self.resources_first: num = random.randint(1, len(available_processors)) available_processors = random.sample(available_processors, num) # map processes processes = part_mapping.get_unmapped_processes() # print("remaining process list: {}".format(processes)) for p in processes: affinity = None scheduler_list = list(self.platform.schedulers()) while affinity is None and len(scheduler_list) > 0: i = random.randrange(0, len(scheduler_list)) scheduler = scheduler_list.pop(i) processors = [ proc for proc in scheduler.processors if proc in available_processors ] if len(processors) == 0: continue i = random.randrange(0, len(processors)) affinity = processors[i] if affinity is None: raise RuntimeError( f"Could not find an appropriate scheduler for any of " f"the processors: {available_processors}") priority = random.randrange(0, 20) info = ProcessMappingInfo(scheduler, affinity, priority) part_mapping.add_process_info(p, info) log.debug( "rand_map: map process %s to scheduler %s and processor %s " "(priority: %d)", p.name, scheduler.name, affinity.name, priority, ) # map channels channels = part_mapping.get_unmapped_channels() for c in channels: capacity = 16 # fixed channel bound this may cause problems suitable_primitives = [] for p in part_mapping.platform.primitives(): src = part_mapping.process_info(c.source).affinity sinks = [ part_mapping.process_info(s).affinity for s in c.sinks ] if p.is_suitable(src, sinks): suitable_primitives.append(p) if len(suitable_primitives) == 0: raise RuntimeError( "rand_map: Mapping failed! No suitable primitive for " "communication from %s to %s found!" % (src.name, str(sinks))) i = random.randrange(0, len(suitable_primitives)) primitive = suitable_primitives[i] info = ChannelMappingInfo(primitive, capacity) part_mapping.add_channel_info(c, info) log.debug( "rand_map: map channel %s to the primitive %s and bound to %d " "tokens" % (c.name, primitive.name, capacity)) # finally check if the mapping is fully specified assert not part_mapping.get_unmapped_processes() assert not part_mapping.get_unmapped_channels() return part_mapping
def center_mu(graph, platform, mu): m = Mapping(graph, platform) m.from_list_random(mu) return m
def center(graph, platform, point): m = Mapping(graph, platform) m.from_list_random(point) return m
def generate_mapping(self, part_mapping=None): """Generates a random mapping The generated mapping takes a partial mapping (that may also be empty) as starting point. All open mapping decisions are taken by selecting the first option randomness derived from the given seed. :param seed: initial seed for the random generator :type seed: integer :param part_mapping: partial mapping to start from :type part_mapping: Mapping """ # generate new mapping if no partial mapping is given if not part_mapping: part_mapping = Mapping(self.graph, self.platform) # check if the platform/graph is equivalent if (not part_mapping.platform is self.platform or not part_mapping.graph is self.graph): raise RuntimeError( "rand_map: Try to map partial mapping of platform,dataflow %s,%s to %s,%s", part_mapping.platform.name, part_mapping.graph.name, self.platform.name, self.graph.name, ) # map processes processes = part_mapping.get_unmapped_processes() # print("remaining process list: {}".format(processes)) for p in processes: scheduler = list(self.platform.schedulers())[0] affinity = scheduler.processors[0] priority = 0 info = ProcessMappingInfo(scheduler, affinity, priority) part_mapping.add_process_info(p, info) log.debug( "rand_map: map process %s to scheduler %s and processor %s " "(priority: %d)", p.name, scheduler.name, affinity.name, priority, ) # map channels channels = part_mapping.get_unmapped_channels() for c in channels: capacity = 4 # fixed channel bound this may cause problems suitable_primitives = [] for p in part_mapping.platform.primitives(): src = part_mapping.process_info(c.source).affinity sinks = [ part_mapping.process_info(s).affinity for s in c.sinks ] if p.is_suitable(src, sinks): suitable_primitives.append(p) if len(suitable_primitives) == 0: raise RuntimeError( "rand_map: Mapping failed! No suitable primitive for " "communication from %s to %s found!" % (src.name, str(sinks))) primitive = suitable_primitives[0] info = ChannelMappingInfo(primitive, capacity) part_mapping.add_channel_info(c, info) log.debug( "rand_map: map channel %s to the primitive %s and bound to %d " "tokens" % (c.name, primitive.name, capacity)) # finally check if the mapping is fully specified assert not part_mapping.get_unmapped_processes() assert not part_mapping.get_unmapped_channels() return part_mapping