Ejemplo n.º 1
0
/** \ingroup m_task_management
 * \brief Changes the CPU affinity of a computation task.
 *
 * When pinning the given task to the first CPU core of the given host, use
 * 0x01 for the mask value. Each bit of the mask value corresponds to each CPU
 * core. See taskset(1) on Linux.
 *
 * \param task a target task
 * \param host the host having a multi-core CPU
 * \param mask the bit mask of a new CPU affinity setting for the task
 *
 *
 * Usage:
 * 0. Define a host with multiple cores.
 *    \<host id="PM0" power="1E8" core="2"/\>
 *
 * 1. Pin a given task to the first CPU core of a host.
 *   MSG_task_set_affinity(task, pm0, 0x01);
 *
 * 2. Pin a given task to the third CPU core of a host. Turn on the third bit of the mask.
 *   MSG_task_set_affinity(task, pm0, 0x04); // 0x04 == 100B
 *
 * 3. Pin a given VM to the first CPU core of a host.
 *   MSG_vm_set_affinity(vm, pm0, 0x01);
 *
 * See examples/msg/cloud/multicore.c for more information.
 *
 *
 * Note:
 * 1. The current code does not allow an affinity of a task to multiple cores.
 * The mask value 0x03 (i.e., a given task will be executed on the first core
 * or the second core) is not allowed. The mask value 0x01 or 0x02 works. See
 * cpu_cas01.c for details.
 *
 * 2. It is recommended to first compare simulation results in both the Lazy
 * and Full calculation modes (using --cfg=cpu/optim:Full or not). Fix
 * cpu_cas01.c if you find wrong results in the Lazy mode.
 *
 */
void MSG_task_set_affinity(msg_task_t task, msg_host_t host, unsigned long mask)
{
  xbt_assert(task, "Invalid parameter");
  xbt_assert(task->simdata, "Invalid parameter");

  if (mask == 0) {
    /* 0 means clear */
    {
      /* We need remove_ext() not throwing exception. */
      void *ret = xbt_dict_get_or_null_ext(task->simdata->affinity_mask_db, (char *) host, sizeof(msg_host_t));
      if (ret != NULL)
        xbt_dict_remove_ext(task->simdata->affinity_mask_db, (char *) host, sizeof(host));
    }
  } else
    xbt_dict_set_ext(task->simdata->affinity_mask_db, (char *) host, sizeof(host), (void *) mask, NULL);

  /* We set affinity data of this task. If the task is being executed, we
   * actually change the affinity setting of the task. Otherwise, this change
   * will be applied when the task is executed. */

  if (!task->simdata->compute) {
    /* task is not yet executed */
    XBT_INFO("set affinity(0x%04lx@%s) for %s (not active now)", mask, MSG_host_get_name(host), MSG_task_get_name(task));
    return;
  }

  {
    smx_synchro_t compute = task->simdata->compute;
    msg_host_t host_now = compute->execution.host;  // simix_private.h is necessary
    if (host_now != host) {
      /* task is not yet executed on this host */
      XBT_INFO("set affinity(0x%04lx@%s) for %s (not active now)", mask, MSG_host_get_name(host), MSG_task_get_name(task));
      return;
    }

    /* task is being executed on this host. so change the affinity now */
    {
      /* check it works. remove me if it works. */
      xbt_assert((unsigned long) xbt_dict_get_or_null_ext(task->simdata->affinity_mask_db, (char *) host, sizeof(msg_host_t)) == mask);
    }

    XBT_INFO("set affinity(0x%04lx@%s) for %s", mask, MSG_host_get_name(host), MSG_task_get_name(task));
    simcall_process_execution_set_affinity(task->simdata->compute, host, mask);
  }
}
Ejemplo n.º 2
0
static graph_node_map_element_t
graph_node_map_search(as_dijkstra_t as, int id)
{
  graph_node_map_element_t elm = (graph_node_map_element_t)
          xbt_dict_get_or_null_ext(as->graph_node_map,
              (char *) (&id),
              sizeof(int));
  return elm;
}
Ejemplo n.º 3
0
static void route_new_dijkstra(as_dijkstra_t as, int src_id,
    int dst_id, sg_platf_route_cbarg_t e_route)
{
  XBT_DEBUG("Load Route from \"%d\" to \"%d\"", src_id, dst_id);
  xbt_node_t src = NULL;
  xbt_node_t dst = NULL;

  graph_node_map_element_t src_elm = (graph_node_map_element_t)
          xbt_dict_get_or_null_ext(as->graph_node_map,
              (char *) (&src_id),
              sizeof(int));
  graph_node_map_element_t dst_elm = (graph_node_map_element_t)
          xbt_dict_get_or_null_ext(as->graph_node_map,
              (char *) (&dst_id),
              sizeof(int));


  if (src_elm)
    src = src_elm->node;

  if (dst_elm)
    dst = dst_elm->node;

  /* add nodes if they don't exist in the graph */
  if (src_id == dst_id && src == NULL && dst == NULL) {
    src = route_graph_new_node(as, src_id, -1);
    dst = src;
  } else {
    if (src == NULL) {
      src = route_graph_new_node(as, src_id, -1);
    }
    if (dst == NULL) {
      dst = route_graph_new_node(as, dst_id, -1);
    }
  }

  /* add link as edge to graph */
  xbt_graph_new_edge(as->route_graph, src, dst, e_route);
}
Ejemplo n.º 4
0
void
xbt_multidict_set_ext(xbt_dict_t mdict,
                      xbt_dynar_t keys, xbt_dynar_t lens,
                      void *data, void_f_pvoid_t free_ctn)
{

  xbt_dict_t thislevel, nextlevel = NULL;
  int i;

  unsigned long int thislen;
  char *thiskey;
  int keys_len = xbt_dynar_length(keys);

  xbt_assert(xbt_dynar_length(keys) == xbt_dynar_length(lens));
  xbt_assert(keys_len, "Can't set a zero-long key set in a multidict");

  XBT_DEBUG("xbt_multidict_set(%p,%d)", mdict, keys_len);

  for (i = 0, thislevel = mdict; i < keys_len - 1;
       i++, thislevel = nextlevel) {

    xbt_dynar_get_cpy(keys, i, &thiskey);
    xbt_dynar_get_cpy(lens, i, &thislen);

    XBT_DEBUG("multi_set: at level %d, len=%ld, key=%p |%*s|", i, thislen,
           thiskey, (int) thislen, thiskey);

    /* search the dict of next level */
    nextlevel = xbt_dict_get_or_null_ext(thislevel, thiskey, thislen);
    if (nextlevel == NULL) {
      /* make sure the dict of next level exists */
      nextlevel = xbt_dict_new();
      XBT_VERB("Create a dict (%p)", nextlevel);
      xbt_dict_set_ext(thislevel, thiskey, thislen, nextlevel,
                       &_free_dict);
    }
  }

  xbt_dynar_get_cpy(keys, i, &thiskey);
  xbt_dynar_get_cpy(lens, i, &thislen);

  xbt_dict_set_ext(thislevel, thiskey, thislen, data, free_ctn);
}
Ejemplo n.º 5
0
/**
 * \brief Retrieve data from the dict (key considered as a uintptr_t)
 *
 * \param dict the dealer of data
 * \param key the key to find data
 * \return the data that we are looking for (or 0 if not found)
 *
 * Mixing uintptr_t keys with regular keys in the same dict is discouraged
 */
XBT_INLINE uintptr_t xbt_dicti_get(xbt_dict_t dict, uintptr_t key)
{
    return (uintptr_t)xbt_dict_get_or_null_ext(dict, (void *)&key, sizeof key);
}
Ejemplo n.º 6
0
/** \ingroup msg_task_usage
 * \brief Executes a parallel task and waits for its termination.
 *
 * \param task a #msg_task_t to execute on the location on which the process is running.
 *
 * \return #MSG_OK if the task was successfully completed, #MSG_TASK_CANCELED
 * or #MSG_HOST_FAILURE otherwise
 */
msg_error_t MSG_parallel_task_execute(msg_task_t task)
{
  xbt_ex_t e;
  simdata_task_t simdata = task->simdata;
  msg_process_t self = SIMIX_process_self();
  simdata_process_t p_simdata = SIMIX_process_self_get_data(self);
  e_smx_state_t comp_state;
  msg_error_t status = MSG_OK;

  TRACE_msg_task_execute_start(task);

  xbt_assert((!simdata->compute) && (task->simdata->isused == 0),
             "This task is executed somewhere else. Go fix your code! %d",
             task->simdata->isused!=NULL);

  XBT_DEBUG("Computing on %s", MSG_process_get_name(MSG_process_self()));

  if (simdata->flops_amount == 0 && !simdata->host_nb) {
    TRACE_msg_task_execute_end(task);
    return MSG_OK;
  }


  TRY {
    if (msg_global->debug_multiple_use)
      MSG_BT(simdata->isused, "Using Backtrace");
    else
      simdata->isused = (void*)1;

    if (simdata->host_nb > 0) {
      simdata->compute = simcall_process_parallel_execute(task->name,
                                                       simdata->host_nb,
                                                       simdata->host_list,
                                                       simdata->flops_parallel_amount,
                                                       simdata->bytes_parallel_amount,
                                                       1.0, -1.0);
      XBT_DEBUG("Parallel execution action created: %p", simdata->compute);
    } else {
      unsigned long affinity_mask = (unsigned long) xbt_dict_get_or_null_ext(simdata->affinity_mask_db, (char *) p_simdata->m_host, sizeof(msg_host_t));
      XBT_DEBUG("execute %s@%s with affinity(0x%04lx)", MSG_task_get_name(task), MSG_host_get_name(p_simdata->m_host), affinity_mask);

      simdata->compute = simcall_process_execute(task->name,
                                              simdata->flops_amount,
                                              simdata->priority,
                                              simdata->bound,
                                              affinity_mask
                                              );

    }
    simcall_set_category(simdata->compute, task->category);
    p_simdata->waiting_action = simdata->compute;
    comp_state = simcall_process_execution_wait(simdata->compute);

    p_simdata->waiting_action = NULL;

    if (msg_global->debug_multiple_use && simdata->isused!=0)
      xbt_ex_free(*(xbt_ex_t*)simdata->isused);
    simdata->isused = 0;

    XBT_DEBUG("Execution task '%s' finished in state %d",
              task->name, (int)comp_state);
  }
  CATCH(e) {
    switch (e.category) {
    case cancel_error:
      status = MSG_TASK_CANCELED;
      break;
    case host_error:
      status = MSG_HOST_FAILURE;
      break;
    default:
      RETHROW;
    }
    xbt_ex_free(e);
  }
  /* action ended, set comm and compute = NULL, the actions is already destroyed
   * in the main function */
  simdata->flops_amount = 0.0;
  simdata->comm = NULL;
  simdata->compute = NULL;
  TRACE_msg_task_execute_end(task);

  MSG_RETURN(status);
}
Ejemplo n.º 7
0
void AsDijkstra::getRouteAndLatency(NetCard *src, NetCard *dst, sg_platf_route_cbarg_t route, double *lat)
{
  getRouteCheckParams(src, dst);
  int src_id = src->id();
  int dst_id = dst->id();

  int *pred_arr = nullptr;
  sg_platf_route_cbarg_t e_route;
  int size = 0;
  xbt_dynar_t nodes = xbt_graph_get_nodes(routeGraph_);

  /* Use the graph_node id mapping set to quickly find the nodes */
  graph_node_map_element_t src_elm = nodeMapSearch(src_id);
  graph_node_map_element_t dst_elm = nodeMapSearch(dst_id);

  int src_node_id = ((graph_node_data_t) xbt_graph_node_get_data(src_elm->node))->graph_id;
  int dst_node_id = ((graph_node_data_t) xbt_graph_node_get_data(dst_elm->node))->graph_id;

  /* if the src and dst are the same */
  if (src_node_id == dst_node_id) {

    xbt_node_t node_s_v = xbt_dynar_get_as(nodes, src_node_id, xbt_node_t);
    xbt_node_t node_e_v = xbt_dynar_get_as(nodes, dst_node_id, xbt_node_t);
    xbt_edge_t edge = xbt_graph_get_edge(routeGraph_, node_s_v, node_e_v);

    if (edge == nullptr)
      THROWF(arg_error, 0, "No route from '%s' to '%s'", src->name(), dst->name());

    e_route = (sg_platf_route_cbarg_t) xbt_graph_edge_get_data(edge);

    for (auto link: *e_route->link_list) {
      route->link_list->insert(route->link_list->begin(), link);
      if (lat)
        *lat += static_cast<Link*>(link)->getLatency();
    }

  }

  route_cache_element_t elm = nullptr;
  if (routeCache_) {  /* cache mode  */
    elm = (route_cache_element_t) xbt_dict_get_or_null_ext(routeCache_, (char *) (&src_id), sizeof(int));
  }

  if (elm) {                    /* cached mode and cache hit */
    pred_arr = elm->pred_arr;
  } else {                      /* not cached mode, or cache miss */

    int nr_nodes = xbt_dynar_length(nodes);
    double * cost_arr = xbt_new0(double, nr_nodes);      /* link cost from src to other hosts */
    pred_arr = xbt_new0(int, nr_nodes); /* predecessors in path from src */
    xbt_heap_t pqueue = xbt_heap_new(nr_nodes, xbt_free_f);

    /* initialize */
    cost_arr[src_node_id] = 0.0;

    for (int i = 0; i < nr_nodes; i++) {
      if (i != src_node_id) {
        cost_arr[i] = DBL_MAX;
      }

      pred_arr[i] = 0;

      /* initialize priority queue */
      int *nodeid = xbt_new0(int, 1);
      *nodeid = i;
      xbt_heap_push(pqueue, nodeid, cost_arr[i]);

    }

    /* apply dijkstra using the indexes from the graph's node array */
    while (xbt_heap_size(pqueue) > 0) {
      int *v_id = (int *) xbt_heap_pop(pqueue);
      xbt_node_t v_node = xbt_dynar_get_as(nodes, *v_id, xbt_node_t);
      xbt_edge_t edge = nullptr;
      unsigned int cursor;

      xbt_dynar_foreach(xbt_graph_node_get_outedges(v_node), cursor, edge) {
        xbt_node_t u_node = xbt_graph_edge_get_target(edge);
        graph_node_data_t data = (graph_node_data_t) xbt_graph_node_get_data(u_node);
        int u_id = data->graph_id;
        sg_platf_route_cbarg_t tmp_e_route = (sg_platf_route_cbarg_t) xbt_graph_edge_get_data(edge);
        int cost_v_u = tmp_e_route->link_list->size();    /* count of links, old model assume 1 */

        if (cost_v_u + cost_arr[*v_id] < cost_arr[u_id]) {
          pred_arr[u_id] = *v_id;
          cost_arr[u_id] = cost_v_u + cost_arr[*v_id];
          int *nodeid = xbt_new0(int, 1);
          *nodeid = u_id;
          xbt_heap_push(pqueue, nodeid, cost_arr[u_id]);
        }
      }

      /* free item popped from pqueue */
      xbt_free(v_id);
    }
Ejemplo n.º 8
0
graph_node_map_element_t AsDijkstra::nodeMapSearch(int id)
{
  return (graph_node_map_element_t)xbt_dict_get_or_null_ext(graphNodeMap_, (char *) (&id), sizeof(int));
}
Ejemplo n.º 9
0
/** \ingroup msg_task_usage
 * \brief Executes a parallel task and waits for its termination.
 *
 * \param task a #msg_task_t to execute on the location on which the process is running.
 *
 * \return #MSG_OK if the task was successfully completed, #MSG_TASK_CANCELED
 * or #MSG_HOST_FAILURE otherwise
 */
msg_error_t MSG_parallel_task_execute(msg_task_t task)
{
  simdata_task_t simdata = task->simdata;
  simdata_process_t p_simdata = (simdata_process_t) SIMIX_process_self_get_data();
  e_smx_state_t comp_state;
  msg_error_t status = MSG_OK;

  TRACE_msg_task_execute_start(task);

  xbt_assert((!simdata->compute) && !task->simdata->isused,
             "This task is executed somewhere else. Go fix your code!");

  XBT_DEBUG("Computing on %s", MSG_process_get_name(MSG_process_self()));

  if (simdata->flops_amount == 0 && !simdata->host_nb) {
    TRACE_msg_task_execute_end(task);
    return MSG_OK;
  }

  try {
    simdata->setUsed();

    if (simdata->host_nb > 0) {
      simdata->compute = static_cast<simgrid::simix::Exec*>(
          simcall_execution_parallel_start(task->name, simdata->host_nb,simdata->host_list,
                                                       simdata->flops_parallel_amount, simdata->bytes_parallel_amount,
                                                       1.0, -1.0));
      XBT_DEBUG("Parallel execution action created: %p", simdata->compute);
    } else {
      unsigned long affinity_mask =
         (unsigned long)(uintptr_t) xbt_dict_get_or_null_ext(simdata->affinity_mask_db, (char *) p_simdata->m_host,
                                                             sizeof(msg_host_t));
      XBT_DEBUG("execute %s@%s with affinity(0x%04lx)",
                MSG_task_get_name(task), MSG_host_get_name(p_simdata->m_host), affinity_mask);

          simdata->compute = static_cast<simgrid::simix::Exec*>(
              simcall_execution_start(task->name, simdata->flops_amount, simdata->priority,
                                                 simdata->bound, affinity_mask));
    }
    simcall_set_category(simdata->compute, task->category);
    p_simdata->waiting_action = simdata->compute;
    comp_state = simcall_execution_wait(simdata->compute);

    p_simdata->waiting_action = nullptr;
    simdata->setNotUsed();

    XBT_DEBUG("Execution task '%s' finished in state %d", task->name, (int)comp_state);
  }
  catch (xbt_ex& e) {
    switch (e.category) {
    case cancel_error:
      status = MSG_TASK_CANCELED;
      break;
    case host_error:
      status = MSG_HOST_FAILURE;
      break;
    default:
      throw;
    }
  }

  /* action ended, set comm and compute = nullptr, the actions is already destroyed in the main function */
  simdata->flops_amount = 0.0;
  simdata->comm = nullptr;
  simdata->compute = nullptr;
  TRACE_msg_task_execute_end(task);

  MSG_RETURN(status);
}
Ejemplo n.º 10
0
/** @brief Replaces a set of variables by their values
 *
 * @param b buffer to modify
 * @param patterns variables to substitute in the buffer
 *
 * Both '$toto' and '${toto}' are valid (and the two writing are equivalent).
 *
 * If the variable name contains spaces, use the brace version (ie, ${toto tutu})
 *
 * You can provide a default value to use if the variable is not set in the dict by using
 * '${var:=default}' or '${var:-default}'. These two forms are equivalent, even if they
 * shouldn't to respect the shell standard (:= form should set the value in the dict,
 * but does not) (BUG).
 */
void xbt_strbuff_varsubst(xbt_strbuff_t b, xbt_dict_t patterns)
{

  char *end;                    /* pointers around the parsed chunk */
  int in_simple_quote = 0, in_double_quote = 0;
  int done = 0;

  if (b->data[0] == '\0')
    return;
  end = b->data;

  while (!done) {
    switch (*end) {
    case '\\':
      /* Protected char; pass the protection */
      end++;
      if (*end == '\0')
        THROWF(arg_error, 0, "String ends with \\");
      break;

    case '\'':
      if (!in_double_quote) {
        /* simple quote not protected by double ones, note it */
        in_simple_quote = !in_simple_quote;
      }
      break;
    case '"':
      if (!in_simple_quote) {
        /* double quote protected by simple ones, note it */
        in_double_quote = !in_double_quote;
      }
      break;

    case '$':
      if (!in_simple_quote) {
        /* Go for the substitution. First search the variable name */
        char *beg_var, *end_var;        /* variable name boundary */
        char *beg_subst, *end_subst = NULL;     /* where value should be written to */
        char *value, *default_value = NULL;
        int val_len;
        beg_subst = end;


        if (*(++end) == '{') {
          /* the variable name is enclosed in braces. */
          beg_var = end + 1;
          /* Search name's end */
          end_var = beg_var;
          while (*end_var != '\0' && *end_var != '}') {
            /* TODO: we do not respect the standard for ":=", we should set this value in the dict */
            if (*end_var == ':'
                && ((*(end_var + 1) == '=') || (*(end_var + 1) == '-'))) {
              /* damn, we have a default value */
              char *p = end_var + 1;
              while (*p != '\0' && *p != '}')
                p++;
              if (*p == '\0')
                THROWF(arg_error, 0,
                       "Variable default value not terminated ('}' missing)");

              default_value = xbt_malloc(p - end_var - 1);
              memcpy(default_value, end_var + 2, p - end_var - 2);
              default_value[p - end_var - 2] = '\0';

              end_subst = p + 1;        /* eat '}' */

              break;
            }
            end_var++;
          }
          if (*end_var == '\0')
            THROWF(arg_error, 0,
                   "Variable name not terminated ('}' missing)");

          if (!end_subst)       /* already set if there's a default value */
            end_subst = end_var + 1;    /* also kill the } in the name */

          if (end_var == beg_var)
            THROWF(arg_error, 0, "Variable name empty (${} is not valid)");


        } else {
          /* name given directly */
          beg_var = end;
          end_var = beg_var;
          while (*end_var != '\0' && *end_var != ' ' && *end_var != '\t'
                 && *end_var != '\n')
            end_var++;
          end_subst = end_var;
          if (end_var == beg_var)
            THROWF(arg_error, 0, "Variable name empty ($ is not valid)");
        }
/*        XBT_DEBUG("var='%.*s'; subst='%.*s'; End_var = '%s'",
            end_var-beg_var,beg_var,
            end_subst-beg_subst,beg_subst,
            end_var);*/

        /* ok, we now have the variable name. Search the dictionary for the substituted value */
        value =
            xbt_dict_get_or_null_ext(patterns, beg_var, end_var - beg_var);
/*        XBT_DEBUG("Deal with '%s'",b->data);
        XBT_DEBUG("Search for %.*s, found %s (default value = %s)\n",
            end_var-beg_var,beg_var,
            (value?value:"(no value)"),
            (default_value?default_value:"(no value)"));*/

        if (value)
          value = xbt_strdup(value);
        else if (default_value)
          value = xbt_strdup(default_value);
        else
          value = xbt_strdup("");

        /* En route for the actual substitution */
        val_len = strlen(value);
//        XBT_DEBUG("val_len = %d, key_len=%d",val_len,end_subst-beg_subst);
        if (val_len <= end_subst - beg_subst) {
          /* enough room to do the substitute in place */
//          XBT_DEBUG("Substitute key name by its value: ie '%.*s' by '%.*s'",end_subst-beg_subst,beg_subst,val_len,value);
          memmove(beg_subst, value, val_len);   /* substitute */
//          XBT_DEBUG("String is now: '%s'",b->data);
/*          XBT_DEBUG("Move end of string closer (%d chars moved) :\n-'%.*s%.*s'\n+'%.*s%s'",
              b->used - (end_subst - b->data) + 1,
              beg_subst-b->data,b->data,
              b->used-(end_subst-b->data)+1,beg_subst+val_len,
              beg_subst-b->data,b->data,
              end_subst);*/
          memmove(beg_subst + val_len, end_subst, b->used - (end_subst - b->data) + 1); /* move the end of the string closer */
//          XBT_DEBUG("String is now: '%s'",b->data);
          end = beg_subst + val_len;    /* update the currently explored char in the overall loop */
//          XBT_DEBUG("end of substituted section is now '%s'",end);
          b->used -= end_subst - beg_subst - val_len;   /* update string buffer used size */
//          XBT_DEBUG("Used:%d end:%d ending char:%d",b->used,end-b->data,*end);
        } else {
          /* we have to extend the data area */
          int tooshort =
              val_len - (end_subst - beg_subst) + 1 /*don't forget \0 */ ;
          int newused = b->used + tooshort;
          end += tooshort;      /* update the pointer of the overall loop */
//          XBT_DEBUG("Too short (by %d chars; %d chars left in area)",val_len- (end_subst-beg_subst), b->size - b->used);
          if (newused > b->size) {
            /* We have to realloc the data area before (because b->size is too small). We have to update our pointers, too */
            char *newdata = realloc(b->data,
                                    b->used + MAX(minimal_increment,
                                                  tooshort));
            int offset = newdata - b->data;
            b->data = newdata;
            b->size = b->used + MAX(minimal_increment, tooshort);
            end += offset;
            beg_subst += offset;
            end_subst += offset;
          }
          memmove(beg_subst + val_len, end_subst, b->used - (end_subst - b->data) + 1); /* move the end of the string a bit further */
          memmove(beg_subst, value, val_len);   /* substitute */
          b->used = newused;
//          XBT_DEBUG("String is now: %s",b->data);
        }
        free(value);

        free(default_value);

        end--;                  /* compensate the next end++ */
      }
      break;

    case '\0':
      done = 1;
    }
    end++;
  }
}