your trace files and slow down or speed up the simulation between two
consecutive calls by using an adjustment file. (See the documentation.)
+ * Fixed computation of timings for MPI_Send, MPI_Recv but possibly also others
+ We've found a bug that prevented SMPI to account for MPI_Send, MPI_Recv
+ and others (in some cases) in a correct way. That is, the smpi/os, smpi/or
+ values were ignored in some cases. The timings of these functions can now
+ be significantly different.
-- $date Da SimGrid team <simgrid-devel@lists.gforge.inria.fr>
class Process;
class Context;
class ContextFactory;
-
+ class Mutex;
}
}
typedef simgrid::simix::Context *smx_context_t;
typedef simgrid::simix::Process *smx_process_t;
+/**
+ * \ingroup simix_synchro_management
+ */
+typedef simgrid::simix::Mutex *smx_mutex_t;
+
#else
typedef struct s_smx_context *smx_context_t;
typedef struct s_smx_process *smx_process_t;
+typedef struct s_smx_mutex *smx_mutex_t;
#endif
-
-
-SG_BEGIN_DECL()
-
/**************************** Scalar Values **********************************/
typedef union u_smx_scalar u_smx_scalar_t;
/** @} */
/* ******************************** Synchro ************************************ */
-/**
- * \ingroup simix_synchro_management
- */
-typedef struct s_smx_mutex *smx_mutex_t;
+
/**
* \ingroup simix_synchro_management
*/
extern int smx_context_guard_size;
extern int smx_context_guard_size_was_set;
+SG_BEGIN_DECL()
+
XBT_PUBLIC(xbt_dynar_t) SIMIX_process_get_runnable(void);
XBT_PUBLIC(smx_process_t) SIMIX_process_from_PID(int PID);
XBT_PUBLIC(xbt_dynar_t) SIMIX_processes_as_dynar(void);
/************************** Synchro simcalls **********************************/
XBT_PUBLIC(smx_mutex_t) simcall_mutex_init(void);
XBT_PUBLIC(void) SIMIX_mutex_destroy(smx_mutex_t mutex);
+XBT_PUBLIC(smx_mutex_t) SIMIX_mutex_dup(smx_mutex_t mutex);
XBT_PUBLIC(void) simcall_mutex_lock(smx_mutex_t mutex);
XBT_PUBLIC(int) simcall_mutex_trylock(smx_mutex_t mutex);
XBT_PUBLIC(void) simcall_mutex_unlock(smx_mutex_t mutex);
#ifndef _XBT_THREAD_H
#define _XBT_THREAD_H
+#include <simgrid/simix.h>
+
#include "xbt/misc.h" /* SG_BEGIN_DECL */
#include "xbt/function_types.h"
case SIMCALL_MUTEX_LOCK: {
smx_mutex_t mutex = simcall_mutex_lock__get__mutex(req);
#if HAVE_MC
- s_smx_mutex_t temp_mutex;
+ simgrid::mc::Remote<simgrid::simix::Mutex> temp_mutex;
if (mc_model_checker != nullptr) {
- mc_model_checker->process().read(&temp_mutex, remote(mutex));
- mutex = &temp_mutex;
+ mc_model_checker->process().read(temp_mutex.getBuffer(), remote(mutex));
+ mutex = temp_mutex.getBuffer();
}
#endif
else
type = "Mutex TRYLOCK";
- s_smx_mutex_t mutex;
- mc_model_checker->process().read_bytes(&mutex, sizeof(mutex),
+ simgrid::mc::Remote<simgrid::simix::Mutex> mutex;
+ mc_model_checker->process().read_bytes(mutex.getBuffer(), sizeof(mutex),
remote(
req->call == SIMCALL_MUTEX_LOCK
? simcall_mutex_lock__get__mutex(req)
));
s_xbt_swag_t mutex_sleeping;
mc_model_checker->process().read_bytes(&mutex_sleeping, sizeof(mutex_sleeping),
- remote(mutex.sleeping));
+ remote(mutex.getBuffer()->sleeping));
args = bprintf("locked = %d, owner = %d, sleeping = %d",
- mutex.locked,
- mutex.owner != nullptr ? (int) mc_model_checker->process().resolveProcess(
- simgrid::mc::remote(mutex.owner))->pid : -1,
+ mutex.getBuffer()->locked,
+ mutex.getBuffer()->owner != nullptr ? (int) mc_model_checker->process().resolveProcess(
+ simgrid::mc::remote(mutex.getBuffer()->owner))->pid : -1,
mutex_sleeping.count);
break;
}
void SIMIX_clean(void)
{
if (smx_cleaned) return; // to avoid double cleaning by java and C
+
+#if HAVE_SMPI
+ if (SIMIX_process_count()>0){
+ if(smpi_process_initialized()){
+ xbt_die("Process exited without calling MPI_Finalize - Killing simulation");
+ }else{
+ XBT_WARN("Process called exit when leaving - Skipping cleanups");
+ return;
+ }
+ }
+#endif
+
smx_cleaned = 1;
XBT_DEBUG("SIMIX_clean called. Simulation's over.");
if (!xbt_dynar_is_empty(simix_global->process_to_run) && SIMIX_get_clock() == 0.0) {
{
unsigned int cursor;
smx_synchro_t synchro;
+ // The default result is -1 -- this means, "nothing is ready".
+ // It can be changed below, but only if something matches.
simcall_comm_testany__set__result(simcall, -1);
if (MC_is_active() || MC_record_replay_is_active()){
public:
std::string name;
std::function<void()> code;
- void *data = nullptr;
- const char *hostname = nullptr;
- double kill_time = 0.0;
- xbt_dict_t properties = nullptr;
- bool auto_restart = false;
+ void *data = nullptr;
+ const char *hostname = nullptr;
+ double kill_time = 0.0;
+ xbt_dict_t properties = nullptr;
+ bool auto_restart = false;
};
class Process {
public:
// TODO, replace with boost intrusive container hooks
- s_xbt_swag_hookup_t process_hookup = { nullptr, nullptr }; /* simix_global->process_list */
- s_xbt_swag_hookup_t synchro_hookup = { nullptr, nullptr }; /* {mutex,cond,sem}->sleeping */
+ s_xbt_swag_hookup_t process_hookup = { nullptr, nullptr }; /* simix_global->process_list */
+ s_xbt_swag_hookup_t synchro_hookup = { nullptr, nullptr }; /* {mutex,cond,sem}->sleeping */
s_xbt_swag_hookup_t host_proc_hookup = { nullptr, nullptr }; /* smx_host->process_lis */
- s_xbt_swag_hookup_t destroy_hookup = { nullptr, nullptr }; /* simix_global->process_to_destroy */
+ s_xbt_swag_hookup_t destroy_hookup = { nullptr, nullptr }; /* simix_global->process_to_destroy */
- unsigned long pid = 0;
+ unsigned long pid = 0;
unsigned long ppid = 0;
simgrid::xbt::string name;
- sg_host_t host = nullptr; /* the host on which the process is running */
+ sg_host_t host = nullptr; /* the host on which the process is running */
smx_context_t context = nullptr; /* the context (uctx/raw/thread) that executes the user function */
// TODO, pack them
std::exception_ptr exception;
- bool blocked = false;
- bool suspended = false;
+ bool blocked = false;
+ bool suspended = false;
bool auto_restart = false;
- sg_host_t new_host = nullptr; /* if not null, the host on which the process must migrate to */
+ sg_host_t new_host = nullptr; /* if not null, the host on which the process must migrate to */
smx_synchro_t waiting_synchro = nullptr; /* the current blocking synchro if any */
- xbt_fifo_t comms = nullptr; /* the current non-blocking communication synchros */
- xbt_dict_t properties = nullptr;
+ xbt_fifo_t comms = nullptr; /* the current non-blocking communication synchros */
+ xbt_dict_t properties = nullptr;
s_smx_simcall_t simcall;
- void *data = nullptr; /* kept for compatibility, it should be replaced with moddata */
+ void *data = nullptr; /* kept for compatibility, it should be replaced with moddata */
xbt_dynar_t on_exit = nullptr; /* list of functions executed when the process dies */
std::function<void()> code;
smx_timer_t kill_timer = nullptr;
- int segment_index = 0; /*Reference to an SMPI process' data segment. Default value is -1 if not in SMPI context*/
+ int segment_index = 0; /*Reference to an SMPI process' data segment. Default value is -1 if not in SMPI context*/
};
}
+
/* Copyright (c) 2007-2015. The SimGrid Team.
* All rights reserved. */
}
/*********************************** Mutex ************************************/
-smx_mutex_t simcall_HANDLER_mutex_init(smx_simcall_t simcall){
- return SIMIX_mutex_init();
-}
-/**
- * \brief Initialize a mutex.
- *
- * Allocs and creates the data for the mutex.
- * \return A mutex
- */
-smx_mutex_t SIMIX_mutex_init(void)
+namespace simgrid {
+namespace simix {
+
+Mutex::Mutex()
{
- XBT_IN("()");
- simgrid::simix::Process p; /* useful to initialize sleeping swag */
+ XBT_IN("(%p)", this);
+ // Useful to initialize sleeping swag:
+ simgrid::simix::Process p;
+ this->sleeping = xbt_swag_new(xbt_swag_offset(p, synchro_hookup));
+ XBT_OUT();
+}
- smx_mutex_t mutex = xbt_new0(s_smx_mutex_t, 1);
- mutex->locked = 0;
- mutex->sleeping = xbt_swag_new(xbt_swag_offset(p, synchro_hookup));
+Mutex::~Mutex()
+{
+ XBT_IN("(%p)", this);
+ xbt_swag_free(this->sleeping);
XBT_OUT();
- return mutex;
}
-/**
- * \brief Handles a mutex lock simcall.
- * \param simcall the simcall
- */
-void simcall_HANDLER_mutex_lock(smx_simcall_t simcall, smx_mutex_t mutex)
+void Mutex::lock(smx_process_t issuer)
{
- XBT_IN("(%p)",simcall);
+ XBT_IN("(%p; %p)", this, issuer);
/* FIXME: check where to validate the arguments */
smx_synchro_t synchro = nullptr;
- smx_process_t process = simcall->issuer;
- if (mutex->locked) {
+ if (this->locked) {
/* FIXME: check if the host is active ? */
/* Somebody using the mutex, use a synchronization to get host failures */
- synchro = SIMIX_synchro_wait(process->host, -1);
- synchro->simcalls.push_back(simcall);
- simcall->issuer->waiting_synchro = synchro;
- xbt_swag_insert(simcall->issuer, mutex->sleeping);
+ synchro = SIMIX_synchro_wait(issuer->host, -1);
+ synchro->simcalls.push_back(&issuer->simcall);
+ issuer->waiting_synchro = synchro;
+ xbt_swag_insert(issuer, this->sleeping);
} else {
/* mutex free */
- mutex->locked = 1;
- mutex->owner = simcall->issuer;
- SIMIX_simcall_answer(simcall);
+ this->locked = true;
+ this->owner = issuer;
+ SIMIX_simcall_answer(&issuer->simcall);
}
XBT_OUT();
}
-int simcall_HANDLER_mutex_trylock(smx_simcall_t simcall, smx_mutex_t mutex){
- return SIMIX_mutex_trylock(mutex, simcall->issuer);
-}
-/**
- * \brief Tries to lock a mutex.
+/** Tries to lock the mutex for a process
*
- * Tries to lock a mutex, return 1 if the mutex is unlocked, else 0.
- * This function does not block and wait for the mutex to be unlocked.
- * \param mutex The mutex
- * \param issuer The process that tries to acquire the mutex
- * \return 1 - mutex free, 0 - mutex used
+ * \param issuer the process that tries to acquire the mutex
+ * \return whether we managed to lock the mutex
*/
-int SIMIX_mutex_trylock(smx_mutex_t mutex, smx_process_t issuer)
+bool Mutex::try_lock(smx_process_t issuer)
{
- XBT_IN("(%p, %p)",mutex,issuer);
- if (mutex->locked){
+ XBT_IN("(%p, %p)", this, issuer);
+ if (this->locked) {
XBT_OUT();
- return 0;
+ return false;
}
- mutex->locked = 1;
- mutex->owner = issuer;
+ this->locked = true;
+ this->owner = issuer;
XBT_OUT();
- return 1;
+ return true;
}
-void simcall_HANDLER_mutex_unlock(smx_simcall_t simcall, smx_mutex_t mutex){
- SIMIX_mutex_unlock(mutex, simcall->issuer);
-}
-/**
- * \brief Unlocks a mutex.
+/** Unlock a mutex for a process
*
* Unlocks the mutex and gives it to a process waiting for it.
* If the unlocker is not the owner of the mutex nothing happens.
* If there are no process waiting, it sets the mutex as free.
- * \param mutex The mutex
- * \param issuer The process trying to unlock the mutex
*/
-void SIMIX_mutex_unlock(smx_mutex_t mutex, smx_process_t issuer)
+void Mutex::unlock(smx_process_t issuer)
{
- XBT_IN("(%p, %p)",mutex,issuer);
+ XBT_IN("(%p, %p)", this, issuer);
/* If the mutex is not owned by the issuer, that's not good */
- if (issuer != mutex->owner)
+ if (issuer != this->owner)
THROWF(mismatch_error, 0, "Cannot release that mutex: it was locked by %s (pid:%d), not by you.",
- SIMIX_process_get_name(mutex->owner),SIMIX_process_get_PID(mutex->owner));
+ SIMIX_process_get_name(this->owner),SIMIX_process_get_PID(this->owner));
- if (xbt_swag_size(mutex->sleeping) > 0) {
+ if (xbt_swag_size(this->sleeping) > 0) {
/*process to wake up */
- smx_process_t p = (smx_process_t) xbt_swag_extract(mutex->sleeping);
+ smx_process_t p = (smx_process_t) xbt_swag_extract(this->sleeping);
delete p->waiting_synchro;
p->waiting_synchro = nullptr;
- mutex->owner = p;
+ this->owner = p;
SIMIX_simcall_answer(&p->simcall);
} else {
/* nobody to wake up */
- mutex->locked = 0;
- mutex->owner = nullptr;
+ this->locked = false;
+ this->owner = nullptr;
}
XBT_OUT();
}
-/**
- * \brief Destroys a mutex.
- *
- * Destroys and frees the mutex's memory.
- * \param mutex A mutex
- */
+}
+}
+
void SIMIX_mutex_destroy(smx_mutex_t mutex)
{
- XBT_IN("(%p)",mutex);
- if (mutex){
- xbt_swag_free(mutex->sleeping);
- xbt_free(mutex);
- }
- XBT_OUT();
+ if (mutex != nullptr)
+ intrusive_ptr_release(mutex);
+}
+
+XBT_PUBLIC(smx_mutex_t) SIMIX_mutex_dup(smx_mutex_t mutex)
+{
+ if (mutex != nullptr)
+ intrusive_ptr_add_ref(mutex);
+ return mutex;
+}
+
+smx_mutex_t simcall_HANDLER_mutex_init(smx_simcall_t simcall)
+{
+ return new simgrid::simix::Mutex();
+}
+
+// Simcall handlers:
+
+void simcall_HANDLER_mutex_lock(smx_simcall_t simcall, smx_mutex_t mutex)
+{
+ mutex->lock(simcall->issuer);
+}
+
+int simcall_HANDLER_mutex_trylock(smx_simcall_t simcall, smx_mutex_t mutex)
+{
+ return mutex->try_lock(simcall->issuer);
+}
+
+void simcall_HANDLER_mutex_unlock(smx_simcall_t simcall, smx_mutex_t mutex)
+{
+ mutex->unlock(simcall->issuer);
}
/********************************* Condition **********************************/
/* FIXME: what happens if the issuer is not the owner of the mutex? */
if (mutex != nullptr) {
cond->mutex = mutex;
- SIMIX_mutex_unlock(mutex, issuer);
+ mutex->unlock(issuer);
}
synchro = SIMIX_synchro_wait(issuer->host, timeout);
#ifndef _SIMIX_SYNCHRO_PRIVATE_H
#define _SIMIX_SYNCHRO_PRIVATE_H
+#include <atomic>
+
#include "xbt/base.h"
#include "xbt/swag.h"
#include "xbt/xbt_os_thread.h"
#include "src/simix/popping_private.h"
-typedef struct s_smx_mutex {
- unsigned int locked;
- smx_process_t owner;
- xbt_swag_t sleeping; /* list of sleeping process */
-} s_smx_mutex_t;
+namespace simgrid {
+namespace simix {
+
+class XBT_PUBLIC() Mutex {
+public:
+ Mutex();
+ ~Mutex();
+ Mutex(Mutex const&) = delete;
+ Mutex& operator=(Mutex const&) = delete;
+
+ void lock(smx_process_t issuer);
+ bool try_lock(smx_process_t issuer);
+ void unlock(smx_process_t issuer);
+
+ bool locked = false;
+ smx_process_t owner = nullptr;
+ // List of sleeping processes:
+ xbt_swag_t sleeping = nullptr;
+
+ // boost::intrusive_ptr<Mutex> support:
+ friend void intrusive_ptr_add_ref(Mutex* mutex)
+ {
+ auto previous = ++mutex->refcount_;
+ xbt_assert(previous != 0);
+ (void) previous;
+ }
+ friend void intrusive_ptr_release(Mutex* mutex)
+ {
+ auto count = mutex->refcount_--;
+ if (count == 0)
+ delete mutex;
+ }
+private:
+ std::atomic_int_fast32_t refcount_ { 1 };
+};
+
+}
+}
typedef struct s_smx_cond {
smx_mutex_t mutex;
XBT_PRIVATE void SIMIX_synchro_destroy(smx_synchro_t synchro);
XBT_PRIVATE void SIMIX_synchro_finish(smx_synchro_t synchro);
-XBT_PRIVATE smx_mutex_t SIMIX_mutex_init(void);
-XBT_PRIVATE int SIMIX_mutex_trylock(smx_mutex_t mutex, smx_process_t issuer);
-XBT_PRIVATE void SIMIX_mutex_unlock(smx_mutex_t mutex, smx_process_t issuer);
-
XBT_PRIVATE smx_cond_t SIMIX_cond_init(void);
XBT_PRIVATE void SIMIX_cond_broadcast(smx_cond_t cond);
XBT_PRIVATE void SIMIX_cond_signal(smx_cond_t cond);
* under the terms of the license (GNU LGPL) which comes with this package. */
#include <xbt/config.hpp>
+#include <boost/tokenizer.hpp>
+#include <algorithm>
#include "private.h"
#include "xbt/virtu.h"
// These are taken from surf/network.c and generalized to have more values for each factor
typedef struct s_smpi_factor_multival *smpi_os_factor_multival_t;
typedef struct s_smpi_factor_multival { // FIXME: this should be merged (deduplicated) with s_smpi_factor defined in network_smpi.c
- long factor;
- int nb_values;
- double values[4];//arbitrary set to 4
+ long factor=0;
+ std::vector<double> values;
} s_smpi_factor_multival_t;
-xbt_dynar_t smpi_os_values = nullptr;
-xbt_dynar_t smpi_or_values = nullptr;
-xbt_dynar_t smpi_ois_values = nullptr;
+std::vector<s_smpi_factor_multival_t> smpi_os_values;
+std::vector<s_smpi_factor_multival_t> smpi_or_values;
+std::vector<s_smpi_factor_multival_t> smpi_ois_values;
static simgrid::config::Flag<double> smpi_wtime_sleep(
"smpi/wtime", "Minimum time to inject inside a call to MPI_Wtime", 0.0);
static simgrid::config::Flag<double> smpi_test_sleep(
"smpi/test", "Minimum time to inject inside a call to MPI_Test", 1e-4);
-static int factor_cmp(const void *pa, const void *pb)
+static int factor_cmp(const s_smpi_factor_multival_t& pa, const s_smpi_factor_multival_t& pb)
{
- return ((static_cast<const s_smpi_factor_multival_t*>(pa))->factor > (static_cast<const s_smpi_factor_multival_t*>(pb))->factor) ? 1 :
- ((static_cast<const s_smpi_factor_multival_t*>(pa))->factor < (static_cast<const s_smpi_factor_multival_t*>(pb))->factor) ? -1 : 0;
+ return (pa.factor > pb.factor) ? 1 :
+ (pa.factor < pb.factor) ? -1 : 0;
}
-static xbt_dynar_t parse_factor(const char *smpi_coef_string)
+static std::vector<s_smpi_factor_multival_t> parse_factor(const char *smpi_coef_string)
{
- char *value = nullptr;
- unsigned int iter = 0;
+ std::vector<s_smpi_factor_multival_t> smpi_factor;
s_smpi_factor_multival_t fact;
- fact.nb_values=0;
- unsigned int i=0;
- xbt_dynar_t radical_elements2 = nullptr;
-
- xbt_dynar_t smpi_factor = xbt_dynar_new(sizeof(s_smpi_factor_multival_t), nullptr);
- xbt_dynar_t radical_elements = xbt_str_split(smpi_coef_string, ";");
- xbt_dynar_foreach(radical_elements, iter, value) {
- memset(&fact, 0, sizeof(s_smpi_factor_multival_t));
- radical_elements2 = xbt_str_split(value, ":");
- if (xbt_dynar_length(radical_elements2) <2 || xbt_dynar_length(radical_elements2) > 5)
+
+ /** Setup the tokenizer that parses the string **/
+ typedef boost::tokenizer<boost::char_separator<char>> Tokenizer;
+ boost::char_separator<char> sep(";");
+ boost::char_separator<char> factor_separator(":");
+ std::string tmp_string(smpi_coef_string);
+ Tokenizer tokens(tmp_string, sep);
+
+ /**
+ * Iterate over patterns like A:B:C:D;E:F;G:H
+ * These will be broken down into:
+ * A --> B, C, D
+ * E --> F
+ * G --> H
+ */
+ for (Tokenizer::iterator token_iter = tokens.begin();
+ token_iter != tokens.end(); token_iter++) {
+ Tokenizer factor_values(*token_iter, factor_separator);
+
+ if (factor_values.begin() == factor_values.end()) {
xbt_die("Malformed radical for smpi factor: '%s'", smpi_coef_string);
- for(i =0; i<xbt_dynar_length(radical_elements2);i++ ){
+ }
+ unsigned int iteration = 0;
+ for (Tokenizer::iterator factor_iter = factor_values.begin();
+ factor_iter != factor_values.end(); factor_iter++, iteration++) {
char *errmsg;
- if (i==0) {
- errmsg = bprintf("Invalid factor in chunk #%d: %%s", iter+1);
- fact.factor = xbt_str_parse_int(xbt_dynar_get_as(radical_elements2, i, char *), errmsg);
- } else {
- errmsg = bprintf("Invalid factor value %d in chunk #%d: %%s", i, iter+1);
- fact.values[fact.nb_values] = xbt_str_parse_double(xbt_dynar_get_as(radical_elements2, i, char *), errmsg);
- fact.nb_values++;
+
+ if (factor_iter == factor_values.begin()) { /* first element */
+ errmsg = bprintf("Invalid factor in chunk #%zu: %%s", smpi_factor.size()+1);
+ fact.factor = xbt_str_parse_int(factor_iter->c_str(), errmsg);
+ }
+ else {
+ errmsg = bprintf("Invalid factor value %d in chunk #%zu: %%s", iteration, smpi_factor.size()+1);
+ fact.values.push_back(xbt_str_parse_double((*factor_iter).c_str(), errmsg));
}
xbt_free(errmsg);
}
- xbt_dynar_push_as(smpi_factor, s_smpi_factor_multival_t, fact);
- XBT_DEBUG("smpi_factor:\t%ld : %d values, first: %f", fact.factor, fact.nb_values ,fact.values[0]);
- xbt_dynar_free(&radical_elements2);
+ smpi_factor.push_back(fact);
+ XBT_DEBUG("smpi_factor:\t%ld : %zu values, first: %f", fact.factor, smpi_factor.size(), fact.values[0]);
}
- xbt_dynar_free(&radical_elements);
- xbt_dynar_sort(smpi_factor, &factor_cmp);
- xbt_dynar_foreach(smpi_factor, iter, fact) {
- XBT_DEBUG("smpi_factor:\t%ld : %d values, first: %f", fact.factor, fact.nb_values ,fact.values[0]);
+ std::sort(smpi_factor.begin(), smpi_factor.end(), &factor_cmp);
+ for (auto& fact : smpi_factor) {
+ XBT_DEBUG("smpi_factor:\t%ld : %zu values, first: %f", fact.factor, smpi_factor.size() ,fact.values[0]);
}
+
return smpi_factor;
}
static double smpi_os(double size)
{
- if (smpi_os_values == nullptr) {
+ if (smpi_os_values.empty()) {
smpi_os_values = parse_factor(xbt_cfg_get_string("smpi/os"));
- smpi_register_static(smpi_os_values, xbt_dynar_free_voidp);
}
- unsigned int iter = 0;
- s_smpi_factor_multival_t fact;
double current=0.0;
// Iterate over all the sections that were specified and find the right
// value. (fact.factor represents the interval sizes; we want to find the
// section that has fact.factor <= size and no other such fact.factor <= size)
// Note: parse_factor() (used before) already sorts the dynar we iterate over!
- xbt_dynar_foreach(smpi_os_values, iter, fact) {
+ for (auto& fact : smpi_os_values) {
if (size <= fact.factor) { // Values already too large, use the previously
// computed value of current!
XBT_DEBUG("os : %f <= %ld return %f", size, fact.factor, current);
current = fact.values[0]+fact.values[1]*size;
}
}
- XBT_DEBUG("os : %f > %ld return %f", size, fact.factor, current);
+ XBT_DEBUG("Searching for smpi/os: %f is larger than the largest boundary, return %f", size, current);
return current;
}
static double smpi_ois(double size)
{
- if (smpi_ois_values == nullptr) {
+ if (smpi_ois_values.empty()) {
smpi_ois_values = parse_factor(xbt_cfg_get_string("smpi/ois"));
- smpi_register_static(smpi_ois_values, xbt_dynar_free_voidp);
}
- unsigned int iter = 0;
- s_smpi_factor_multival_t fact;
double current=0.0;
// Iterate over all the sections that were specified and find the right value. (fact.factor represents the interval
// sizes; we want to find the section that has fact.factor <= size and no other such fact.factor <= size)
// Note: parse_factor() (used before) already sorts the dynar we iterate over!
- xbt_dynar_foreach(smpi_ois_values, iter, fact) {
+ for (auto& fact : smpi_ois_values) {
if (size <= fact.factor) { // Values already too large, use the previously computed value of current!
XBT_DEBUG("ois : %f <= %ld return %f", size, fact.factor, current);
return current;
current = fact.values[0]+fact.values[1]*size;
}
}
- XBT_DEBUG("ois : %f > %ld return %f", size, fact.factor, current);
+ XBT_DEBUG("Searching for smpi/ois: %f is larger than the largest boundary, return %f", size, current);
return current;
}
static double smpi_or(double size)
{
- if (smpi_or_values == nullptr) {
+ if (smpi_or_values.empty()) {
smpi_or_values = parse_factor(xbt_cfg_get_string("smpi/or"));
- smpi_register_static(smpi_or_values, xbt_dynar_free_voidp);
}
- unsigned int iter = 0;
- s_smpi_factor_multival_t fact;
double current=0.0;
// Iterate over all the sections that were specified and find the right value. (fact.factor represents the interval
// sizes; we want to find the section that has fact.factor <= size and no other such fact.factor <= size)
// Note: parse_factor() (used before) already sorts the dynar we iterate over!
- xbt_dynar_foreach(smpi_or_values, iter, fact) {
+ for (auto fact : smpi_or_values) {
if (size <= fact.factor) { // Values already too large, use the previously
// computed value of current!
XBT_DEBUG("or : %f <= %ld return %f", size, fact.factor, current);
current=fact.values[0]+fact.values[1]*size;
}
}
- XBT_DEBUG("or : %f > %ld return %f", size, fact.factor, current);
+ XBT_DEBUG("smpi_or: %f is larger than largest boundary, return %f", size, current);
return current;
}
{
xbt_dynar_t comms;
int i;
- int* map;
int flag = 0;
- int size = 0;
*index = MPI_UNDEFINED;
comms = xbt_dynar_new(sizeof(smx_synchro_t), nullptr);
- map = xbt_new(int, count);
+ std::vector<int> map; /** Maps all matching comms back to their location in requests **/
for(i = 0; i < count; i++) {
if ((requests[i] != MPI_REQUEST_NULL) && requests[i]->action && !(requests[i]->flags & PREPARED)) {
xbt_dynar_push(comms, &requests[i]->action);
- map[size] = i;
- size++;
+ map.push_back(i);
}
}
- if(size > 0) {
+ if(!map.empty()) {
//multiplier to the sleeptime, to increase speed of execution, each failed testany will increase it
static int nsleeps = 1;
if(smpi_test_sleep > 0)
simcall_process_sleep(nsleeps*smpi_test_sleep);
- i = simcall_comm_testany(comms);
- // not MPI_UNDEFINED, as this is a simix return code
- if(i != -1) {
- *index = map[i];
+ i = simcall_comm_testany(comms); // The i-th element in comms matches!
+ if (i != -1) { // -1 is not MPI_UNDEFINED but a SIMIX return code. (nothing matches)
+ *index = map[i];
finish_wait(&requests[*index], status);
- if (requests[*index] != MPI_REQUEST_NULL && (requests[*index]->flags & NON_PERSISTENT))
- requests[*index] = MPI_REQUEST_NULL;
- flag = 1;
- nsleeps=1;
- }else{
+ flag = 1;
+ nsleeps = 1;
+ if (requests[*index] != MPI_REQUEST_NULL && (requests[*index]->flags & NON_PERSISTENT)) {
+ requests[*index] = MPI_REQUEST_NULL;
+ }
+ } else {
nsleeps++;
}
- }else{
- //all requests are null or inactive, return true
- flag=1;
+ } else {
+ flag = 0; // all requests are null or inactive, return false
smpi_empty_status(status);
}
- xbt_free(map);
xbt_dynar_free(&comms);
return flag;
}
}
} elsif (/<cluster/) {
- die ("Unparsable cluster tag. Either provide an hostfile yourself or give the attributes prefix, radical and suffix in that order on the <cluster line");
+ die ("Unparsable cluster tag. smpirun uses a primitive regular expression to parse cluster tags. Either provide a hostfile yourself or give the attributes prefix, radical and suffix IN THAT ORDER and ON THE SAME LINE as the opening tag (<cluster)");
}' ${PLATFORM} >> ${HOSTFILE}
fi
UNROLLEDHOSTFILETMP=0
* under the terms of the license (GNU LGPL) which comes with this package. */
#include <stdio.h>
+#include <math.h>
#include <xbt/xbt_os_time.h>
#include "xbt/heap.h"
-#include "xbt/sysdep.h" /* calloc, printf */
+#include "xbt/sysdep.h"
#define MAX_TEST 1000000
if (pa > pb)
return 1;
- if (pa == pb)
- return 0;
- return -1;
+ if (pa < pb)
+ return -1;
+ return 0;
}
static void test_reset_heap(xbt_heap_t * heap, int size)
qsort(tab, size, sizeof(double), compare_double);
for (i = 0; i < size; i++) {
- /* printf("%g" " ", xbt_heap_maxkey(heap)); */
- if (xbt_heap_maxkey(heap) != tab[i]) {
+ if (fabs(xbt_heap_maxkey(heap) - tab[i]) > 1e-9) {
fprintf(stderr, "Problem !\n");
exit(1);
}