Source code for tokio.tools.topology

#!/usr/bin/env python
"""Perform operations based on the mapping of a job to network topology
"""

import math
import warnings
import tokio.connectors.craysdb as craysdb
from . import jobinfo as jobinfo

[docs]def get_job_diameter(jobid, nodemap_cache_file=None, jobinfo_cache_file=None): """Calculate the diameter of a job An extremely crude way to reduce a job's node allocation into a scalar metric. Assumes nodes are equally capable and fall on a 3D network; calculates the center of mass of the job's node positions. Args: jobid (str): A logical job id from which nodes are determined and their topological placement is determined nodemap_cache_file (str): Full path to the file containing the cached contents to be used to determine the node position map jobinfo_cache_file (str): Full path to the file containing the cached contents to be used to convert the job id into a node list Returns: dict: Contains three keys representing three ways in which a job's radius can be expressed. Keys are: * job_min_radius: The smallest distance between the job's center of mass and a job node * job_max_radius: The largest distance between the job's center of mass and a job node * job_avg_radius: The average distance between the job's center of mass and all job nodes """ node_list = jobinfo.get_job_nodes(jobid=jobid, cache_file=jobinfo_cache_file) proc_table = craysdb.CraySdbProc(cache_file=nodemap_cache_file) node_positions = [] if len(node_list) == 0: warnings.warn("no valid job_info received from jobinfo.get_job_nodes()") return {} for jobnode in node_list: if not jobnode.startswith('nid'): warnings.warn("unable to parse jobnode '%s' for jobid '%s'" % (jobnode, jobid)) return {} nid_num = int(jobnode.lstrip('nid')) node_x = proc_table[nid_num]['x_coord'] node_y = proc_table[nid_num]['y_coord'] node_z = proc_table[nid_num]['z_coord'] node_positions.append((node_x, node_y, node_z)) # Three dimensional topology center = [0.0, 0.0, 0.0] for node_position in node_positions: center[0] += node_position[0] center[1] += node_position[1] center[2] += node_position[2] center[0] /= float(len(node_positions)) center[1] /= float(len(node_positions)) center[2] /= float(len(node_positions)) min_r = 10000.0 max_r = 0.0 avg_r = 0.0 for node_position in node_positions: r2 = (node_position[0] - center[0])**2.0 r2 += (node_position[1] - center[1])**2.0 r2 += (node_position[2] - center[2])**2.0 r = math.sqrt(r2) if r < min_r: min_r = r if r > max_r: max_r = r avg_r += r return { "job_min_radius": min_r, "job_max_radius": max_r, "job_avg_radius": avg_r / float(len(node_positions)), }