Source code for hdeeprm.resource

"""
Core class and functionality for defining the Resource Hierarchy in the Decision System.
"""

from batsim.batsim import Job

[docs]class Core: """Core representing a compute resource in the Platform. Cores process Jobs inside the Platform. They are uniquely identifiable in Batsim and provide a computing capability for a given power consumption. Attributes: processor (dict): Parent Processor data structure. Fields: | node (:class:`dict`) - Parent Node data structure. Fields: | cluster (:class:`dict`) - Parent Cluster data structure. Fields: | platform (:class:`dict`) - Root Platform data structure. Fields: | total_nodes (:class:`int`) - Total Nodes in the Platform. | total_processors (:class:`int`) - Total Processors in the Platform. | total_cores (:class:`int`) - Total Cores in the Platform. | job_limits (:class:`dict`) - Resource request limits for any Job. Fields: | max_time (:class:`int`) - Maximum requested time in seconds. | max_core (:class:`int`) - Maximum requested Cores. | max_mem (:class:`int`) - Maximum requested Memory in MB. | max_mem_bw (:class:`int`) - Maximum requested Memory BW in GB/s. | reference_machine (:class:`dict`) - Reference host for measures. Fields: | clock_rate (:class:`float`) - Machine clock speed. | dpflop_vector_width (:class:`int`) - Width of vector operations in 32B blocks. | reference_speed (:class:`float`) - Speed for tranforming time into operations. | clusters (list(:class:`dict`)) - Reference to all Clusters in the Platform. | local_nodes (list(:class:`dict`)) - Reference to local Nodes to the Cluster. | max_mem (:class:`int`) - Maximum memory capacity of the Node in MB. | current_mem (:class:`int`) - Current memory capacity of the Node in MB. | local_processors (list(:class:`dict`)) - Reference to local Procs to the Node. | max_mem_bw (:class:`float`) - Maximum memory BW capacity of the Processor in GB/s. | current_mem_bw (:class:`float`) - Current memory BW capacity of the Processor in GB/s. | gflops_per_core (:class:`float`) - Maximum GFLOPs per Core in the Processor. | power_per_core (:class:`float`) - Maximum Watts per Core in the Processor. | local_cores (list(:class:`.Core`)) - Reference to local Cores to the Processor. bs_id (int): Unique identification. Also used in Batsim. state (dict): Defines the current state of the Core. Data fields: | pstate (:class:`int`) - P-state for the Core. | current_gflops (:class:`float`) - Current computing capability in GFLOPs. | current_power (:class:`float`) - Current power consumption in Watts. | served_job (batim.batsim.Job) - Job being served by the Core. """ def __init__(self, processor: dict, bs_id: int) -> None: self.processor = processor self.bs_id = bs_id # By default, core is idle self.state = { 'pstate': 3, 'current_gflops': 0.0, 'current_power': 0.05 * self.processor['power_per_core'], # When active, the Core is serving a Job which is stored as part of its state # Remaining operations and updates along simulation are tracked 'served_job': None }
[docs] def set_state(self, new_pstate: int, now: float, new_served_job: Job = None) -> None: """Sets the state of the Core. It modifies the availability, computing speed and power consumption. It also establishes a new served Job in case the Core is now active. Args: new_pstate (int): New P-state for the Core. now (float): Current simulation time in seconds. new_served_job (batsim.batsim.Job): Reference to the Job now being served by the Core. Defaults to None. """ # Active core if new_pstate in (0, 1): if not self.state['served_job']: new_served_job.last_update = now new_served_job.remaining_ops = new_served_job.req_ops self.state['served_job'] = new_served_job self.processor['current_mem_bw'] -= new_served_job.mem_bw self.processor['node']['current_mem'] -= new_served_job.mem else: self.update_completion(now) # 100% Power self.state['current_power'] = self.processor['power_per_core'] if new_pstate == 0: # 100% GFLOPS self.state['current_gflops'] = self.processor['gflops_per_core'] else: # 75% GFLOPS self.state['current_gflops'] = 0.75 * self.processor['gflops_per_core'] # Inactive core elif new_pstate in (2, 3): if self.state['served_job']: self.processor['current_mem_bw'] += self.state['served_job'].mem_bw self.processor['node']['current_mem'] += self.state['served_job'].mem self.state['served_job'] = None # 0% GFLOPS self.state['current_gflops'] = 0.0 if new_pstate == 2: # 15% Power self.state['current_power'] = 0.15 * self.processor['power_per_core'] else: # 5% Power self.state['current_power'] = 0.05 * self.processor['power_per_core'] else: raise ValueError('Error: unknown P-state') self.state['pstate'] = new_pstate
[docs] def update_completion(self, now: float) -> None: """Updates the Job operations left. Calculates the amount of operations that have been processed using the time span from last update. Args: now (float): Current simulation time in seconds. """ time_delta = now - self.state['served_job'].last_update self.state['served_job'].remaining_ops -= self.state['current_gflops'] * time_delta self.state['served_job'].last_update = now
[docs] def get_remaining_per(self) -> float: """Provides the remaining percentage of the Job being served. Calculated by dividing the remaining operations by the total requested on arrival. """ return self.state['served_job'].remaining_ops / self.state['served_job'].req_ops