Functions

agent_scheduler_eval.c File Reference

#include <stdlib.h>
#include <stdio.h>
#include "utility.h"
#include "server.h"
#include "agent.h"
#include "gs_storage.h"
#include "problem.h"
#include "comm_data.h"
Include dependency graph for agent_scheduler_eval.c:

Go to the source code of this file.

Functions

static double gs_agent_perf_model_score (gs_problem_t *problem, gs_server_t *server)
static double gs_agent_complexity_score (gs_problem_t *problem, gs_server_t *server)
 Calculate the complexity score for a problem.
double gs_agent_get_server_score (gs_problem_t *problem, gs_server_t *server)

Detailed Description

These functions were originally in agent_scheduler, but they've been moved to a separate file to avoid dependence on other agent stuff when linking this into the server.

Definition in file agent_scheduler_eval.c.


Function Documentation

static double gs_agent_complexity_score ( gs_problem_t *  problem,
gs_server_t *  server 
) [static]

Calculate the complexity score for a problem.

Evaluate the complexity information string from the problem, using the scalar problem arguments IF AVAILABLE. This should give the number of flops required to solve the problem. Use this value along with the speed/load of the machine in Mflop/s to come up an estimated time for solving the problem in seconds which is returned.

param problem -- Pointer to the problem data structure param server -- Pointer to the server data structure

Returns:
A complexity score for the problem

Definition at line 110 of file agent_scheduler_eval.c.

{
  icl_hash_t *symtab;
  gs_argument_t *argptr = NULL;
  char *complexitystr = NULL;
  double complexity = -1.0;
  double problem_kflop = -1.0;
  double effective_speed = -1.0;
  double computational_score = -1.0;

  if(!problem || !server) {
    ERRPRINTF("Bad args, returning score of 2000.0\n");
    return 2000.0;
  }

  symtab = icl_hash_create(11, NULL);

  if(!symtab) {
    LOGPRINTF("could not create hash table; ");
    LOGPRINTF("assuming complexity=1000000 (1 gflop of work)\n");
    complexity = 1000000.00;    /* a gigaflop of work */
  }
  else {
    /* Insert scalar input arguments into a hash table */
    for(argptr = problem->arglist; argptr != NULL; argptr = argptr->next)
      if((argptr->objecttype == GS_SCALAR) && (argptr->inout != GS_OUT))
        icl_hash_insert(symtab, argptr->name, &(argptr->expr_val));

    /* Evaluate complexity expression */
    complexitystr = gs_problem_getinfo(problem, "COMPLEXITY", "1000000");

    if(gs_expr_d(complexitystr, &complexity, symtab) < 0) {
      LOGPRINTF("Complexity string %s could not be evaluated; ", complexitystr);
      LOGPRINTF("assuming complexity=1000000 (1 gflop of work)\n");
      complexity = 1000000.00;    /* a gigaflop of work */
    }
  }

  problem_kflop = complexity / 1000.0;

  /* calculation per eijkhout */
  effective_speed = ((double) server->kflops * (double) server->ncpu) /
      (((double) server->workload / 100.0) + 1.0);

  /* The reflects the seconds required to solve the problem, so the smaller
   * the score, the better it is 
   */
  computational_score = (double) problem_kflop / (double) effective_speed;

  DBGPRINTF("Scheduling info:\n");
  DBGPRINTF("\tserver_kflops %d\n", server->kflops);
  DBGPRINTF("\tserver_ncpu %d\n", server->ncpu);
  DBGPRINTF("\tserver_workload %d\n", server->workload);
  DBGPRINTF("\tproblem_kflop %f\n", problem_kflop);
  DBGPRINTF("\teffective_speed %f\n", effective_speed);
  DBGPRINTF("\tcomputational_score %g\n", computational_score);

  if(symtab)
    icl_hash_destroy(symtab, NULL, NULL);

  return(computational_score);
}

Here is the call graph for this function:

Here is the caller graph for this function:

double gs_agent_get_server_score ( gs_problem_t *  problem,
gs_server_t *  server 
)

Gets the server computation time estimate for the given problem.

Definition at line 178 of file agent_scheduler_eval.c.

{
  double score;

  score = gs_agent_perf_model_score(problem, server);

  if(score < 0)
    score = gs_agent_complexity_score(problem, server);

  return score;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static double gs_agent_perf_model_score ( gs_problem_t *  problem,
gs_server_t *  server 
) [static]

Definition at line 24 of file agent_scheduler_eval.c.

{
  double enum_pos, est_time = -1.0;
  gs_argument_t *argptr = NULL;
  gs_arg_enum_t *arg_enum;
  icl_hash_t *symtab;

  if(!problem || !server) {
    ERRPRINTF("Bad args\n");
    return -1.0;
  }

  if(!strcmp(server->perf_expr, GS_NO_MODEL_UPDATE))
    return -1.0;

  if(gs_construct_scalar_hashtable(&symtab, problem, GS_IN) < 0) {
    /* skip scheduling since scalars aren't available */
    return -1.0;
  }

  for(argptr = problem->arglist; argptr != NULL; argptr = argptr->next) {
    enum_pos = 0.0;

    if(argptr->arg_enum) {
      int found_enum_match = 0;

      for(arg_enum=argptr->arg_enum; arg_enum != NULL; arg_enum=arg_enum->next) {
        if((strcmp(arg_enum->val, "other") == 0) ||
           ((argptr->datatype == GS_CHAR) && !strncmp(argptr->data, arg_enum->val, 1)) ||
           ((argptr->datatype != GS_CHAR) && (argptr->expr_val == atof(arg_enum->val))))
        {
          void *ht;

          /* replace actual value in hash table with enum position */

          ht = icl_hash_find(symtab, argptr->name);

          if(!ht)
            ERRPRINTF("Warning: expected to find '%s' in hash table\n",
              argptr->name);
          else
            *((double *)ht) = enum_pos;
 
          found_enum_match = 1;
          break;
        }

        enum_pos += 1.0;
      }

      if(!found_enum_match) {
        ERRPRINTF("No match in model for arg %s\n", argptr->name);
        return -1.0;
      }
    }
  }

  if(gs_expr_d(server->perf_expr, &est_time, symtab) < 0) {
    LOGPRINTF("Perf model expr '%s' could not be evaluated; ", 
       server->perf_expr);
    return -1.0;
  }

  if(symtab)
    icl_hash_destroy(symtab, NULL, NULL);

  return(est_time);
}

Here is the call graph for this function:

Here is the caller graph for this function: