1
1
openmpi/ompi/mca/coll/tuned/coll_tuned_dynamic_rules.c
Graham Fagg 607bdf51b6 Last Cleanup BEFORE adding last two methods and final cross over points.
- new mca param calls
- move printfs to OPAL_OUTPUT

This commit was SVN r7692.
2005-10-11 18:51:03 +00:00

306 строки
9.9 KiB
C

/*
* Copyright (c) 2004-2005 The Trustees of Indiana University.
* All rights reserved.
* Copyright (c) 2004-2005 The Trustees of the University of Tennessee.
* All rights reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "coll_tuned.h"
#include "mpi.h"
#include "ompi/include/constants.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "coll_tuned_dynamic_rules.h"
int static rule_count = 0;
int static cond_count = 0;
/* makes a rule */
/* this is hanging in space until linked to either other rules or a */
/* collective decision function */
rule_t* mk_rule ()
{
rule_t* ptr;
ptr = (rule_t*) calloc (1, sizeof(rule_t));
if (!ptr) {
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:mk_rule calloc on mk_rule failed!"));
exit (-1);
}
/* set values in the hanging rule */
ptr->rule_id = rule_count++;
return (ptr);
}
/* adds a condition to a rule */
int mk_and_add_condition_to_rule (rule_t* rule, param_index_t param,
condition_op_t op, int target)
{
condition_t* ptr;
condition_t* last;
if (!rule) {
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:mk_and_add_condition_to_rule rule given is NULL?!\n"));
return (-2);
}
if (param>=PARAMS) {
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:mk_and_add_condition_to_rule param given is %d?!\n", param));
return (-3);
}
ptr = (condition_t*) calloc (1, sizeof(condition_t));
if (!ptr) {
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:mk_and_add_condition_to_rule calloc failed!\n"));
return (-5);
}
/* set values in the condition */
ptr->cond_id = cond_count++;
ptr->param = param;
ptr->op = op;
ptr->value = target;
/* set values in the rule */
if (rule->nconditions) { /* if we already have conditions add to the last one */
last = rule->last_condition;
last->next = ptr;
}
else { /* its the very first / head condition */
rule->first_condition = ptr;
}
/* common to both all cases */
rule->nconditions++;
rule->last_condition = ptr;
return (0);
}
/* attaches a rules/collective functions TO a rule (not otherway round) */
int set_rule_links (rule_t * rule, ifp true_fptr, int* true_extraargs,
ifp false_fptr, int* false_extraargs,
rule_t* true_rule, rule_t* false_rule)
{
if (!rule) {
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:set_rule_links rule is NULL?"));
return (-2);
}
/* check rule results.. we must have one set for true and one for false */
if ((true_fptr)&&(true_rule)) {
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:set_rule_links BAD. Two links for TRUE on rule %d!", rule->rule_id));
return (-6);
}
if ((false_fptr)&&(false_rule)) {
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:set_rule_links BAD. Two links for FALSE on rule %d!", rule->rule_id));
return (-7);
}
if ((!true_fptr)&&(!true_rule)) {
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:set_rule_links BAD. NO links for TRUE on rule %d!", rule->rule_id));
return (-8);
}
if ((!false_fptr)&&(!false_rule)) {
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:set_rule_links BAD. NO links for FALSE on rule %d!", rule->rule_id));
return (-9);
}
/* can set the links now */
rule->true_fptr = true_fptr;
rule->true_extraargs = true_extraargs;
rule->next_true_rule = (struct rules_s *) true_rule;
rule->false_fptr = false_fptr;
rule->false_extraargs = false_extraargs;
rule->next_false_rule = (struct rules_s *) false_rule;
return (0);
}
/* free rule (and all attached conditions */
/* oneday multiple rules might be able to share conditions to save memory */
int free_rule (rule_t *rule)
{
condition_t* ptr;
condition_t* next;
int i;
if (!rule) {
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:free_rule rule is NULL?"));
return (-2);
}
/* free conditions first */
if (rule->nconditions) {
ptr = rule->first_condition;
for (i=0;i<rule->nconditions;i++) {
next = ptr->next;
free (ptr);
ptr = next;
}
}
/* all conditions freed, free the rule */
free (rule);
return (0);
}
/* evaluates a rule and returns the final function pointer that matches */
int eval_rule (rule_t *rule, params_t *params, ifp* fptr, int** extraargs)
{
rule_t* currentrule;
condition_t* currentcond;
int true=1;
if (!rule) {
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:eval_rule rule given is NULL?!"));
return (-2);
}
/* first special case is a very fast path... sorta not really grr */
if (!rule->nconditions) {
#ifdef VERBOSE
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:eval_rule Rule %d has no conditions so forcing first available",
rule->rule_id));
#endif /* VERBOSE */
*fptr = rule->true_fptr;
return (0);
}
/* ok we have some conditions so start the evaluation */
/* make it as lazy as possible, so a single false condition bumps us */
currentrule = rule;
while (currentrule) { /* rules to evaluate */
#ifdef RULEVERBOSE
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:eval_rule evaluating rule %d ", currentrule->rule_id));
#endif
/* eval each of the current rules conditions */
/* we do this until we have either: */
/* (a) completed all conditions and are still true */
/* (b) found a single false */
/* once we have either a true true or false we can then check */
/* the next values and see if we are returning a function */
/* OR skipping to the next rule and hense iterate */
true = 1; /* we are ok so far */
/* first get the first condition to eval */
currentcond = currentrule->first_condition;
while ((currentcond)&&(true)) { /* while conditions to eval */
#ifdef RULEVERBOSE
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:eval_rule eval cond %d ", currentcond->cond_id));
#endif
switch (currentcond->op) {
case LT: if (params->values[currentcond->param] < currentcond->value) {true = 1;}
else {true = 0;}
break;
case LTEQ: if (params->values[currentcond->param] <= currentcond->value) {true = 1;}
else {true = 0;}
break;
case GT: if (params->values[currentcond->param] > currentcond->value) {true = 1;}
else {true = 0;}
break;
case GTEQ: if (params->values[currentcond->param] >= currentcond->value) {true = 1;}
else {true = 0;}
break;
case EQ: if (params->values[currentcond->param] == currentcond->value) {true = 1;}
else {true = 0;}
break;
default:
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:eval_rule BAD operator of value %d rule %d cond %d",
currentcond->op, currentrule->rule_id,
currentcond->cond_id));
true = 0;
return (-1); /* ?! what else can I do, should have caught before */
} /* switch on condition operator */
/* if we are still true we go to the next condition if there is one */
/* if there is not another then we are truely true */
/* else if we are false, immediately fall out */
if (!true) {
#ifdef RULEVERBOSE
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:eval_rule eval cond %d returned FALSE", currentcond->cond_id));
#endif
break; /* if false drop out asap */
}
if ((true)&&(currentcond->next)) { /* next condition to check */
#ifdef RULEVERBOSE
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:eval_rule eval cond %d returned TRUE. Moving to next",
currentcond->cond_id));
#endif
currentcond = currentcond->next;
}
else { /* we are true with no more conditions to check */
#ifdef RULEVERBOSE
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:eval_rule eval cond %d (LAST) returned TRUE.", currentcond->cond_id));
#endif
break; /* so return so we can find out what to do next */
}
} /* while conditions to eval or a false */
/* condition is either fully met or lazy false */
/* we do these IFs in the fasted/most important order */
if ((true)&&(currentrule->true_fptr)) {
#ifdef RULEVERBOSE
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:eval_rule rule %d is TRUE returning fptr", currentrule->rule_id));
#endif
*fptr = currentrule->true_fptr;
*extraargs = currentrule->true_extraargs;
return (0);
}
if ((!true)&&(currentrule->false_fptr)) {
#ifdef RULEVERBOSE
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:eval_rule rule %d is FALSE returning fptr", currentrule->rule_id));
#endif
*fptr = currentrule->false_fptr;
*extraargs = currentrule->false_extraargs;
return (0);
}
if (true) {
#ifdef RULEVERBOSE
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:eval_rule rule %d is TRUE jumping to next rule %d",
currentrule->rule_id, ((rule_t*)(currentrule->next_true_rule))->rule_id));
#endif
currentrule = (rule_t *) currentrule->next_true_rule;
}
else { /* i.e. not true / lazy eval */
#ifdef RULEVERBOSE
OPAL_OUTPUT((mca_coll_tuned_stream, "Eval Rule %d is FALSE jumping to next rule %d",
currentrule->rule_id, ((rule_t*)(currentrule->next_false_rule))->rule_id));
#endif
currentrule = (rule_t *) currentrule->next_false_rule;
}
if (!currentrule) {
OPAL_OUTPUT((mca_colL_tuned_stream, "coll:tuned:dynamic_rules:eval_rule Disaster, we have gone off into the weeds.. panic!"));
exit (-10);
}
}
}