[ofa-general] Re: [PATCH][5] opensm: compute local geometry
Sasha Khapyorsky
sashak at voltaire.com
Sun Nov 30 07:28:18 PST 2008
On 10:59 Tue 11 Nov , Robert Pearson wrote:
> Sasha,
>
> Here is the fifth patch implementing the mesh analysis algorithm.
>
> This patch implements
> - routine to compute characteristics polynomial of a matrix
> - routine to compute the local 'metric' around each switch
> - routine to classify switches into a histogram of local geometry
> classes
>
> Regards,
>
> Bob Pearson
>
> Signed-off-by: Bob Pearson <rpearson at systemfabricworks.com>
> ----
> diff --git a/opensm/opensm/osm_mesh.c b/opensm/opensm/osm_mesh.c
> index 7434fee..9254de3 100644
> --- a/opensm/opensm/osm_mesh.c
> +++ b/opensm/opensm/osm_mesh.c
> @@ -338,6 +338,172 @@ static int determinant(lash_t *p_lash, int deg, int
> rank, int ***m, int *p)
> }
>
> /*
> + * char_poly
> + *
> + * compute the characteristic polynomial of matrix of rank
> + * by computing the determinant of m-x*I and return in poly
> + * as an array. caller must free poly
> + */
> +static int char_poly(lash_t *p_lash, int rank, int **matrix, int **poly)
> +{
> + int ret = -1;
> + int i, j;
> + int ***m = NULL;
> + int *p = NULL;
> + int deg = rank;
> +
> + do {
> + if (!(p = poly_alloc(p_lash, deg))) {
> + break;
> + }
> +
> + if (!(m = pm_alloc(p_lash, rank, deg))) {
> + free(p);
> + p = NULL;
> + break;
> + }
> +
> + for (i = 0; i < rank; i++) {
> + for (j = 0; j < rank; j++) {
> + m[i][j][0] = matrix[i][j];
> + }
> + m[i][i][1] = -1;
> + }
> +
> + if (determinant(p_lash, deg, rank, m, p)) {
> + free(p);
> + p = NULL;
> + break;
> + }
> +
> + ret = 0;
> + } while(0);
> +
> + pm_free(m, rank);
> + *poly = p;
> + return ret;
> +}
> +
> +/*
> + * get_switch_metric
> + *
> + * compute the matrix of minimum distances between each of
> + * the adjacent switch nodes to sw along paths
> + * that do not go through sw. do calculation by
> + * relaxation method
> + * allocate space for the matrix and save in node_t structure
> + */
> +static int get_switch_metric(lash_t *p_lash, int sw)
> +{
> + int ret = -1;
> + int i, j, change;
> + int sw1, sw2, sw3;
> + switch_t *s = p_lash->switches[sw];
> + switch_t *s1, *s2, *s3;
> + int **m;
> + mesh_node_t *node = s->node;
> + int num_links = node->num_links;
> +
> + do {
> + if (!(m = m_alloc(p_lash, num_links)))
> + break;
> +
> + for (i = 0; i < num_links; i++) {
> + sw1 = node->links[i]->switch_id;
> + s1 = p_lash->switches[sw1];
> +
> + /* make all distances big except s1 to itself */
> + for (sw2 = 0; sw2 < p_lash->num_switches; sw2++)
> + p_lash->switches[sw2]->node->temp =
> 0x7fffffff;
> +
> + s1->node->temp = 0;
> +
> + do {
> + change = 0;
> +
> + for (sw2 = 0; sw2 < p_lash->num_switches;
> sw2++) {
> + s2 = p_lash->switches[sw2];
> + if (s2->node->temp == 0x7fffffff)
> + continue;
> + for (j = 0; j < s2->node->num_links;
> j++) {
> + sw3 =
> s2->node->links[j]->switch_id;
> + s3 = p_lash->switches[sw3];
> +
> + if (sw3 == sw)
> + continue;
> +
> + if ((s2->node->temp + 1) <
> s3->node->temp) {
> + s3->node->temp =
> s2->node->temp + 1;
> + change++;
> + }
> + }
> + }
> + } while(change);
As far as I can understand it is minimal hops calculation.
We already have this information in OpenSM switches lmx mtrices. Using
this matrix 'm' could be created as:
for (i = 0; i < num_links; i++) {
sw1 = node->links[i]->switch_id;
s1 = p_lash->switches[sw1];
for (i = 0; i < num_links; i++) {
unsigned lid;
sw2 = node->links[i]->switch_id;
s2 = p_lash->switches[sw2];
lid = cl_ntoh16(osm_node_get_base_lid(s2->p_sw->p_node, 0));
m[i][j] = osm_switch_get_least_hops(s1->p_sw, lid);
}
}
> +
> + for (j = 0; j < num_links; j++) {
> + sw2 = node->links[j]->switch_id;
> + s2 = p_lash->switches[sw2];
> + m[i][j] = s2->node->temp;
> + }
> + }
> +
> + if (char_poly(p_lash, num_links, m, &node->poly)) {
> + m_free(m, num_links);
> + m = NULL;
> + break;
> + }
> +
> + ret = 0;
> + } while(0);
> +
> + node->matrix = m;
> + return ret;
> +}
> +
> +/*
> + * classify_switch
> + *
> + * add switch to histogram of switch types
> + */
> +static void classify_switch(lash_t *p_lash, int sw)
> +{
> + int i;
> + switch_t *s = p_lash->switches[sw];
> + switch_t *s1;
> + mesh_t *mesh = p_lash->mesh;
> +
> + for (i = 0; i < mesh->num_class; i++) {
> + s1 = p_lash->switches[mesh->class_type[i]];
> +
> + if (poly_diff(s->node->num_links, s->node->poly, s1))
> + continue;
> +
> + mesh->class_count[i]++;
> + return;
> + }
> +
> + mesh->class_type[mesh->num_class] = sw;
> + mesh->class_count[mesh->num_class] = 1;
> + mesh->num_class++;
> + return;
> +}
> +
> +/*
> + * get_local_geometry
> + *
> + * analyze the local geometry around each switch
> + */
> +static void get_local_geometry(lash_t *p_lash)
> +{
> + int sw;
> +
> + for (sw = 0; sw < p_lash->num_switches; sw++) {
> + get_switch_metric(p_lash, sw);
> + classify_switch(p_lash, sw);
> + }
> +}
> +
> +/*
> * osm_mesh_cleanup - free per mesh resources
> */
> void osm_mesh_cleanup(lash_t *p_lash)
> @@ -404,6 +570,12 @@ int osm_do_mesh_analysis(lash_t *p_lash)
> return -1;
> }
>
> + /*
> + * get local metric and invariant for each switch
> + * also classify each switch
> + */
> + get_local_geometry(p_lash);
> +
> printf("lash: do_mesh_analysis stub called\n");
>
> OSM_LOG_EXIT(p_log);
>
>
More information about the general
mailing list